<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18141">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Benjamin Keith Ford: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">xml.c, config,c: Add stylesheets and variable list string parsing<br><br>Added functions to open, close, and apply XML Stylesheets<br>to XML documents. Although the presence of libxslt was already<br>being checked by configure, it was only happening if xmldoc was<br>enabled. Now it's checked regardless.<br><br>Added ability to parse a string consisting of comma separated<br>name/value pairs into an ast_variable list. The reverse of<br>ast_variable_list_join().<br><br>Change-Id: I1e1d149be22165a1fb8e88e2903a36bba1a6cf2e<br>---<br>M build_tools/menuselect-deps.in<br>M configure<br>M configure.ac<br>M include/asterisk/config.h<br>M include/asterisk/xml.h<br>M main/config.c<br>M main/xml.c<br>M tests/test_config.c<br>8 files changed, 425 insertions(+), 73 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in</span><br><span>index 161c67b..f66d7bd 100644</span><br><span>--- a/build_tools/menuselect-deps.in</span><br><span>+++ b/build_tools/menuselect-deps.in</span><br><span>@@ -32,6 +32,7 @@</span><br><span> LDAP=@PBX_LDAP@</span><br><span> LIBEDIT=@PBX_LIBEDIT@</span><br><span> LIBXML2=@PBX_LIBXML2@</span><br><span style="color: hsl(120, 100%, 40%);">+LIBXSLT=@PBX_LIBXSLT@</span><br><span> XMLSTARLET=@PBX_XMLSTARLET@</span><br><span> BASH=@PBX_BASH@</span><br><span> LUA=@PBX_LUA@</span><br><span>diff --git a/configure b/configure</span><br><span>index 5bfd90c..22fe0ac 100755</span><br><span>--- a/configure</span><br><span>+++ b/configure</span><br><span>@@ -9406,8 +9406,8 @@</span><br><span> if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl >= 1.1.0" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for openssl >= 1.1.0... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for OPENSSL... " >&6; }</span><br><span> </span><br><span> if test -n "$OPENSSL_CFLAGS"; then</span><br><span> pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"</span><br><span>@@ -9447,7 +9447,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -9468,7 +9468,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_OPENSSL=0</span><br><span>@@ -9497,8 +9497,8 @@</span><br><span> if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl11" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for openssl11... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for OPENSSL... " >&6; }</span><br><span> </span><br><span> if test -n "$OPENSSL_CFLAGS"; then</span><br><span> pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"</span><br><span>@@ -9538,7 +9538,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -9559,7 +9559,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_OPENSSL=0</span><br><span>@@ -9593,8 +9593,8 @@</span><br><span> if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for openssl... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for OPENSSL... " >&6; }</span><br><span> </span><br><span> if test -n "$OPENSSL_CFLAGS"; then</span><br><span> pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"</span><br><span>@@ -9634,7 +9634,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -9655,7 +9655,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_OPENSSL=0</span><br><span>@@ -14095,8 +14095,8 @@</span><br><span> if test "x${PBX_LIBEDIT}" != "x1" -a "${USE_LIBEDIT}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libedit" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for libedit... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBEDIT" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for LIBEDIT... " >&6; }</span><br><span> </span><br><span> if test -n "$LIBEDIT_CFLAGS"; then</span><br><span> pkg_cv_LIBEDIT_CFLAGS="$LIBEDIT_CFLAGS"</span><br><span>@@ -14136,7 +14136,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -14157,7 +14157,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_LIBEDIT=0</span><br><span>@@ -14555,8 +14555,8 @@</span><br><span> if test "x${PBX_JANSSON}" != "x1" -a "${USE_JANSSON}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for jansson >= 2.11" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for jansson >= 2.11... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JANSSON" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for JANSSON... " >&6; }</span><br><span> </span><br><span> if test -n "$JANSSON_CFLAGS"; then</span><br><span> pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS"</span><br><span>@@ -14596,7 +14596,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -14617,7 +14617,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_JANSSON=0</span><br><span>@@ -15134,6 +15134,8 @@</span><br><span> </span><br><span> $as_echo "#define AST_XML_DOCS 1" >>confdefs.h</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> if test "x${PBX_LIBXSLT}" != "x1" -a "${USE_LIBXSLT}" != "no"; then</span><br><span> pbxlibdir=""</span><br><span>@@ -15327,8 +15329,6 @@</span><br><span> </span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> # Check whether --enable-permanent-dlopen was given.</span><br><span> if test "${enable_permanent_dlopen+set}" = set; then :</span><br><span> enableval=$enable_permanent_dlopen; case "${enableval}" in</span><br><span>@@ -15412,7 +15412,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -15458,7 +15458,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -15482,7 +15482,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -15527,7 +15527,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -15551,7 +15551,7 @@</span><br><span> We can't simply define LARGE_OFF_T to be 9223372036854775807,</span><br><span> since some C++ compilers masquerading as C compilers</span><br><span> incorrectly reject 9223372036854775807. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))</span><br><span style="color: hsl(120, 100%, 40%);">+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))</span><br><span> int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721</span><br><span> && LARGE_OFF_T % 2147483647 == 1)</span><br><span> ? 1 : -1];</span><br><span>@@ -16851,8 +16851,6 @@</span><br><span> if (*(data + i) != *(data3 + i))</span><br><span> return 14;</span><br><span> close (fd);</span><br><span style="color: hsl(0, 100%, 40%);">- free (data);</span><br><span style="color: hsl(0, 100%, 40%);">- free (data3);</span><br><span> return 0;</span><br><span> }</span><br><span> _ACEOF</span><br><span>@@ -21279,8 +21277,8 @@</span><br><span> if test "x${PBX_ILBC}" != "x1" -a "${USE_ILBC}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libilbc" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for libilbc... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ILBC" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for ILBC... " >&6; }</span><br><span> </span><br><span> if test -n "$ILBC_CFLAGS"; then</span><br><span> pkg_cv_ILBC_CFLAGS="$ILBC_CFLAGS"</span><br><span>@@ -21320,7 +21318,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -21341,7 +21339,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_ILBC=0</span><br><span>@@ -24000,8 +23998,8 @@</span><br><span> if test "x${PBX_NETSNMP}" != "x1" -a "${USE_NETSNMP}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for netsnmp-agent" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for netsnmp-agent... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for NETSNMP" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for NETSNMP... " >&6; }</span><br><span> </span><br><span> if test -n "$NETSNMP_CFLAGS"; then</span><br><span> pkg_cv_NETSNMP_CFLAGS="$NETSNMP_CFLAGS"</span><br><span>@@ -24041,7 +24039,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -24062,7 +24060,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_NETSNMP=0</span><br><span>@@ -25608,8 +25606,8 @@</span><br><span> if test "x${PBX_PJPROJECT}" != "x1" -a "${USE_PJPROJECT}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpjproject" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for libpjproject... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PJPROJECT" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for PJPROJECT... " >&6; }</span><br><span> </span><br><span> if test -n "$PJPROJECT_CFLAGS"; then</span><br><span> pkg_cv_PJPROJECT_CFLAGS="$PJPROJECT_CFLAGS"</span><br><span>@@ -25649,7 +25647,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -25670,7 +25668,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_PJPROJECT=0</span><br><span>@@ -26861,8 +26859,8 @@</span><br><span> if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python-2.7" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for python-2.7... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for PYTHONDEV... " >&6; }</span><br><span> </span><br><span> if test -n "$PYTHONDEV_CFLAGS"; then</span><br><span> pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"</span><br><span>@@ -26902,7 +26900,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -26923,7 +26921,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_PYTHONDEV=0</span><br><span>@@ -26949,8 +26947,8 @@</span><br><span> if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python2" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for python2... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for PYTHONDEV... " >&6; }</span><br><span> </span><br><span> if test -n "$PYTHONDEV_CFLAGS"; then</span><br><span> pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"</span><br><span>@@ -26990,7 +26988,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -27011,7 +27009,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_PYTHONDEV=0</span><br><span>@@ -27037,8 +27035,8 @@</span><br><span> if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for python... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for PYTHONDEV... " >&6; }</span><br><span> </span><br><span> if test -n "$PYTHONDEV_CFLAGS"; then</span><br><span> pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"</span><br><span>@@ -27078,7 +27076,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -27099,7 +27097,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_PYTHONDEV=0</span><br><span>@@ -27233,8 +27231,8 @@</span><br><span> if test "x${PBX_PORTAUDIO}" != "x1" -a "${USE_PORTAUDIO}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for portaudio-2.0" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for portaudio-2.0... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PORTAUDIO" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for PORTAUDIO... " >&6; }</span><br><span> </span><br><span> if test -n "$PORTAUDIO_CFLAGS"; then</span><br><span> pkg_cv_PORTAUDIO_CFLAGS="$PORTAUDIO_CFLAGS"</span><br><span>@@ -27274,7 +27272,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -27295,7 +27293,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_PORTAUDIO=0</span><br><span>@@ -33244,8 +33242,8 @@</span><br><span> if test "x${PBX_GMIME}" != "x1" -a "${USE_GMIME}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gmime-$ver" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for gmime-$ver... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GMIME" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for GMIME... " >&6; }</span><br><span> </span><br><span> if test -n "$GMIME_CFLAGS"; then</span><br><span> pkg_cv_GMIME_CFLAGS="$GMIME_CFLAGS"</span><br><span>@@ -33285,7 +33283,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -33306,7 +33304,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_GMIME=0</span><br><span>@@ -34681,8 +34679,8 @@</span><br><span> if test "x${PBX_GTK2}" != "x1" -a "${USE_GTK2}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gtk+-2.0" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for gtk+-2.0... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK2" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for GTK2... " >&6; }</span><br><span> </span><br><span> if test -n "$GTK2_CFLAGS"; then</span><br><span> pkg_cv_GTK2_CFLAGS="$GTK2_CFLAGS"</span><br><span>@@ -34722,7 +34720,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -34743,7 +34741,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_GTK2=0</span><br><span>@@ -34792,8 +34790,8 @@</span><br><span> if test "x${PBX_SYSTEMD}" != "x1" -a "${USE_SYSTEMD}" != "no"; then</span><br><span> </span><br><span> pkg_failed=no</span><br><span style="color: hsl(0, 100%, 40%);">-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5</span><br><span style="color: hsl(0, 100%, 40%);">-$as_echo_n "checking for libsystemd... " >&6; }</span><br><span style="color: hsl(120, 100%, 40%);">+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+$as_echo_n "checking for SYSTEMD... " >&6; }</span><br><span> </span><br><span> if test -n "$SYSTEMD_CFLAGS"; then</span><br><span> pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS"</span><br><span>@@ -34833,7 +34831,7 @@</span><br><span> </span><br><span> </span><br><span> if test $pkg_failed = yes; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then</span><br><span>@@ -34854,7 +34852,7 @@</span><br><span> </span><br><span> </span><br><span> elif test $pkg_failed = untried; then</span><br><span style="color: hsl(0, 100%, 40%);">- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span style="color: hsl(120, 100%, 40%);">+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5</span><br><span> $as_echo "no" >&6; }</span><br><span> </span><br><span> PBX_SYSTEMD=0</span><br><span>diff --git a/configure.ac b/configure.ac</span><br><span>index 9eb62b8..0d6817e 100644</span><br><span>--- a/configure.ac</span><br><span>+++ b/configure.ac</span><br><span>@@ -770,11 +770,11 @@</span><br><span> AC_SUBST([DISABLE_XMLDOC])</span><br><span> if test "${DISABLE_XMLDOC}" != "yes"; then</span><br><span> AC_DEFINE([AST_XML_DOCS], 1, [Define to enable XML documentation.])</span><br><span style="color: hsl(0, 100%, 40%);">- AST_EXT_LIB_CHECK([LIBXSLT], [xslt], [xsltLoadStylesheetPI], [libxslt/xsltInternals.h], [${LIBXML2_LIB}], [${LIBXML2_INCLUDE}])</span><br><span style="color: hsl(0, 100%, 40%);">- AST_EXT_LIB_CHECK([LIBXSLT_CLEANUP], [xslt], [xsltCleanupGlobals], [libxslt/xsltInternals.h], [${LIBXML2_LIB}], [${LIBXML2_INCLUDE}])</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> fi</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+AST_EXT_LIB_CHECK([LIBXSLT], [xslt], [xsltLoadStylesheetPI], [libxslt/xsltInternals.h], [${LIBXML2_LIB}], [${LIBXML2_INCLUDE}])</span><br><span style="color: hsl(120, 100%, 40%);">+AST_EXT_LIB_CHECK([LIBXSLT_CLEANUP], [xslt], [xsltCleanupGlobals], [libxslt/xsltInternals.h], [${LIBXML2_LIB}], [${LIBXML2_INCLUDE}])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AC_ARG_ENABLE([permanent-dlopen],</span><br><span> [AS_HELP_STRING([--enable-permanent-dlopen],</span><br><span> [Enable when your libc has a permanent dlopen like musl])],</span><br><span>diff --git a/include/asterisk/config.h b/include/asterisk/config.h</span><br><span>index f4f6c9d..afac229 100644</span><br><span>--- a/include/asterisk/config.h</span><br><span>+++ b/include/asterisk/config.h</span><br><span>@@ -1006,6 +1006,23 @@</span><br><span> const char *name_value_separator, const char *quote_char, struct ast_str **str);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Parse a string into an ast_variable list. The reverse of ast_variable_list_join</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param input The name-value pair string to parse.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param item_separator The string used to separate the list items.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Only the first character in the string will be used.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If NULL, "," will be used.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param name_value_separator The string used to separate each item's name and value.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Only the first character in the string will be used.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If NULL, "=" will be used.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval A pointer to a list of ast_variables.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if there was an error or no variables could be parsed.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_variable *ast_variable_list_from_string(const char *input, const char *item_separator,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name_value_separator);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Update variable value within a config</span><br><span> *</span><br><span> * \param category Category element within the config</span><br><span>diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h</span><br><span>index 13af3c6..9d43560 100644</span><br><span>--- a/include/asterisk/xml.h</span><br><span>+++ b/include/asterisk/xml.h</span><br><span>@@ -21,9 +21,12 @@</span><br><span> * \brief Asterisk XML abstraction layer</span><br><span> */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/vector.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ast_xml_node;</span><br><span> struct ast_xml_doc;</span><br><span> struct ast_xml_xpath_results;</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xslt_doc;</span><br><span> </span><br><span> /*!</span><br><span> * \brief Initialize the XML library implementation.</span><br><span>@@ -184,6 +187,19 @@</span><br><span> */</span><br><span> struct ast_xml_node *ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue);</span><br><span> struct ast_xml_ns *ast_xml_find_namespace(struct ast_xml_doc *doc, struct ast_xml_node *node, const char *ns_name);</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%);">+ * \brief Get the prefix of a namespace.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ns The namespace</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The prefix of the namespace.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_xml_get_ns_prefix(struct ast_xml_ns *ns);</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%);">+ * \brief Get the href of a namespace.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ns The namespace</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The href of the namespace.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> const char *ast_xml_get_ns_href(struct ast_xml_ns *ns);</span><br><span> </span><br><span> /*!</span><br><span>@@ -260,6 +276,15 @@</span><br><span> struct ast_xml_node *ast_xml_xpath_get_first_result(struct ast_xml_xpath_results *results);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Return a specific result node of an XPath query</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param results The XPath results object to get the result from</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param n The index of the result to get</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The nth result in the XPath object on success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xml_node *ast_xml_xpath_get_result(struct ast_xml_xpath_results *results, int n);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Execute an XPath query on an XML document</span><br><span> * \param doc XML document to query</span><br><span> * \param xpath_str The XPath query string to execute on the document</span><br><span>@@ -270,4 +295,80 @@</span><br><span> */</span><br><span> struct ast_xml_xpath_results *ast_xml_query(struct ast_xml_doc *doc, const char *xpath_str);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Namespace definition</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xml_namespace_def {</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *prefix;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *href;</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%);">+AST_VECTOR(ast_xml_namespace_def_vector, struct ast_xml_namespace_def);</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%);">+ * \brief Execute an XPath query on an XML document with namespaces</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param doc XML document to query</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param xpath_str The XPath query string to execute on the document</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param namespaces A vector of ast_xml_namespace structures (not pointers)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return An object containing the results of the XPath query on success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xml_xpath_results *ast_xml_query_with_namespaces(struct ast_xml_doc *doc, const char *xpath_str,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_namespace_def_vector *namespaces);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_LIBXSLT</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Open an XSLT document that resides in memory.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buffer The address where the stylesheet is stored</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param size The number of bytes in the stylesheet</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The stylesheet document. Must be closed with ast_xslt_close().</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xslt_doc *ast_xslt_read_memory(char *buffer, size_t size);</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%);">+ * \brief Open an XSLT document.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param filename stylesheet path.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The stylesheet document. Must be closed with ast_xslt_close().</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xslt_doc *ast_xslt_open(char *filename);</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%);">+ * \brief Close a stylesheet document and free its resources.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param xslt XSLT stylesheet to close</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_xslt_close(struct ast_xslt_doc *xslt);</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%);">+ * \brief Apply an XSLT stylesheet to an XML document</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param xslt XSLT stylesheet to apply.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param xml XML document the stylesheet will be applied to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param params An array of name value pairs to pass as parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ * The array must terminate with a NULL sentinel.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Example: { "name1", "value1", "name2", "value2", NULL }</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return A pointer to the result document which must be freed with ast_xml_close()</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xml_doc *ast_xslt_apply(struct ast_xslt_doc *xslt, struct ast_xml_doc *doc, const char **params);</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%);">+ * \brief Save the results of applying a stylesheet to a string</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buffer[out] A pointer to a char * to receive the address of the result string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The buffer must be freed with ast_xml_free_text().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param length[out] A pointer to an int to receive the result string length.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param result The result document from ast_xslt_apply.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param xslt The stylesheet that was applied.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, any other value on failure.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_xslt_save_result_to_string(char **buffer, int *length, struct ast_xml_doc *result,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xslt_doc *xslt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* HAVE_LIBXSLT */</span><br><span> #endif /* _ASTERISK_XML_H */</span><br><span>diff --git a/main/config.c b/main/config.c</span><br><span>index 92a24de..122e7aa 100644</span><br><span>--- a/main/config.c</span><br><span>+++ b/main/config.c</span><br><span>@@ -722,6 +722,39 @@</span><br><span> return local_str;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_variable *ast_variable_list_from_string(const char *input, const char *item_separator,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name_value_separator)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char item_sep;</span><br><span style="color: hsl(120, 100%, 40%);">+ char nv_sep;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *new_list = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *new_var = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *item_string;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *item;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *item_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *item_value;</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%);">+ return 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%);">+ item_sep = ast_strlen_zero(item_separator) ? ',' : item_separator[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ nv_sep = ast_strlen_zero(name_value_separator) ? '=' : name_value_separator[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ item_string = ast_strip(ast_strdupa(input));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((item = ast_strsep(&item_string, item_sep, AST_STRSEP_ALL))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ item_name = ast_strsep(&item, nv_sep, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ item_value = ast_strsep(&item, nv_sep, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ new_var = ast_variable_new(item_name, item_value, "");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!new_var) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(new_list);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variable_list_append(&new_list, new_var);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return new_list;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)</span><br><span> {</span><br><span> const char *tmp;</span><br><span>diff --git a/main/xml.c b/main/xml.c</span><br><span>index 88c9edf..987f125 100644</span><br><span>--- a/main/xml.c</span><br><span>+++ b/main/xml.c</span><br><span>@@ -36,25 +36,33 @@</span><br><span> #include <libxml/tree.h></span><br><span> #include <libxml/xinclude.h></span><br><span> #include <libxml/xpath.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <libxml/xpathInternals.h></span><br><span> /* libxml2 ast_xml implementation. */</span><br><span> #ifdef HAVE_LIBXSLT</span><br><span> #include <libxslt/xsltInternals.h></span><br><span> #include <libxslt/transform.h></span><br><span style="color: hsl(120, 100%, 40%);">+ #include <libxslt/xsltutils.h></span><br><span> #endif /* HAVE_LIBXSLT */</span><br><span> </span><br><span> </span><br><span> int ast_xml_init(void)</span><br><span> {</span><br><span> LIBXML_TEST_VERSION</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_LIBXSLT</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltInit();</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span> int ast_xml_finish(void)</span><br><span> {</span><br><span> xmlCleanupParser();</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef HAVE_LIBXSLT</span><br><span> #ifdef HAVE_LIBXSLT_CLEANUP</span><br><span> xsltCleanupGlobals();</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltUninit();</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span> #endif</span><br><span> </span><br><span> return 0;</span><br><span>@@ -68,6 +76,8 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ xmlSubstituteEntitiesDefault(1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> doc = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);</span><br><span> if (!doc) {</span><br><span> return NULL;</span><br><span>@@ -309,6 +319,11 @@</span><br><span> return (struct ast_xml_ns *) ns;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_xml_get_ns_prefix(struct ast_xml_ns *ns)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return (const char *) ((xmlNsPtr) ns)->prefix;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> const char *ast_xml_get_ns_href(struct ast_xml_ns *ns)</span><br><span> {</span><br><span> return (const char *) ((xmlNsPtr) ns)->href;</span><br><span>@@ -376,13 +391,24 @@</span><br><span> return (struct ast_xml_node *) ((xmlXPathObjectPtr) results)->nodesetval->nodeTab[0];</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xml_node *ast_xml_xpath_get_result(struct ast_xml_xpath_results *results, int i)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return (struct ast_xml_node *) ((xmlXPathObjectPtr) results)->nodesetval->nodeTab[i];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void ast_xml_xpath_results_free(struct ast_xml_xpath_results *results)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!results) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> xmlXPathFreeObject((xmlXPathObjectPtr) results);</span><br><span> }</span><br><span> </span><br><span> int ast_xml_xpath_num_results(struct ast_xml_xpath_results *results)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!results) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> return ((xmlXPathObjectPtr) results)->nodesetval->nodeNr;</span><br><span> }</span><br><span> </span><br><span>@@ -408,4 +434,149 @@</span><br><span> return (struct ast_xml_xpath_results *) result;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xml_xpath_results *ast_xml_query_with_namespaces(struct ast_xml_doc *doc, const char *xpath_str,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_namespace_def_vector *namespaces)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathContextPtr context;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathObjectPtr result;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!(context = xmlXPathNewContext((xmlDoc *) doc))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Could not create XPath context!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ for (i = 0; i < AST_VECTOR_SIZE(namespaces); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_namespace_def ns = AST_VECTOR_GET(namespaces, i);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (xmlXPathRegisterNs(context, (xmlChar *)ns.prefix,</span><br><span style="color: hsl(120, 100%, 40%);">+ (xmlChar *)ns.href) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathFreeContext(context);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Could not register namespace %s:%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ns.prefix, ns.href);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ result = xmlXPathEvalExpression((xmlChar *) xpath_str, context);</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathFreeContext(context);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!result) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Error for query: %s\n", xpath_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathFreeObject(result);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(5, "No results for query: %s\n", xpath_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return (struct ast_xml_xpath_results *) result;</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%);">+#ifdef HAVE_LIBXSLT</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_xslt_doc *ast_xslt_open(char *filename)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltStylesheet *xslt;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlDoc *xml;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlSubstituteEntitiesDefault(1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ xml = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!xml) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ if (xmlXIncludeProcess(xml) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlFreeDoc(xml);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathOrderDocElems(xml);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!(xslt = xsltParseStylesheetDoc(xml))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlFreeDoc(xml);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ return (struct ast_xslt_doc *) xslt;</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%);">+struct ast_xslt_doc *ast_xslt_read_memory(char *buffer, size_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltStylesheet *xslt;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlDoc *doc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!buffer) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ xmlSubstituteEntitiesDefault(1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!(doc = xmlParseMemory(buffer, (int) size))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ if (xmlXIncludeProcess(doc) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlFreeDoc(doc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ if (!(xslt = xsltParseStylesheetDoc(doc))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlFreeDoc(doc);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+ return (struct ast_xslt_doc *) xslt;</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%);">+void ast_xslt_close(struct ast_xslt_doc *axslt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!axslt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</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%);">+ xsltFreeStylesheet((xsltStylesheet *) axslt);</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%);">+struct ast_xml_doc *ast_xslt_apply(struct ast_xslt_doc *axslt, struct ast_xml_doc *axml, const char **params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltStylesheet *xslt = (xsltStylesheet *)axslt;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlDoc *xml = (xmlDoc *)axml;</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltTransformContextPtr ctxt;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlNs *ns;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlDoc *res;</span><br><span style="color: hsl(120, 100%, 40%);">+ int options = XSLT_PARSE_OPTIONS;</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%);">+ * Normally we could just call xsltApplyStylesheet() without creating</span><br><span style="color: hsl(120, 100%, 40%);">+ * our own transform context but we need to pass parameters to it</span><br><span style="color: hsl(120, 100%, 40%);">+ * that have namespace prefixes and that's not supported. Instead</span><br><span style="color: hsl(120, 100%, 40%);">+ * we have to create a transform context, iterate over the namespace</span><br><span style="color: hsl(120, 100%, 40%);">+ * declarations in the stylesheet (not the incoming xml document),</span><br><span style="color: hsl(120, 100%, 40%);">+ * and add them to the transform context's xpath context.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The alternative would be to pass the parameters with namespaces</span><br><span style="color: hsl(120, 100%, 40%);">+ * as text strings but that's not intuitive and results in much</span><br><span style="color: hsl(120, 100%, 40%);">+ * slower performance than adding the namespaces here.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ ctxt = xsltNewTransformContext(xslt, xml);</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltSetCtxtParseOptions(ctxt, options);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (ns = xslt->doc->children->nsDef; ns; ns = ns->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (xmlXPathRegisterNs(ctxt->xpathCtxt, ns->prefix, ns->href) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlXPathFreeContext(ctxt->xpathCtxt);</span><br><span style="color: hsl(120, 100%, 40%);">+ xsltFreeTransformContext(ctxt);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = xsltApplyStylesheetUser(xslt, xml, params, NULL, NULL, ctxt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return (struct ast_xml_doc *)res;</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%);">+int ast_xslt_save_result_to_string(char **buffer, int *length, struct ast_xml_doc *result,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xslt_doc *axslt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return xsltSaveResultToString((xmlChar **)buffer, length, (xmlDoc *)result, (xsltStylesheet *)axslt);</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%);">+#endif /* defined(HAVE_LIBXSLT) */</span><br><span> #endif /* defined(HAVE_LIBXML2) */</span><br><span>diff --git a/tests/test_config.c b/tests/test_config.c</span><br><span>index 5b44b44..1a0ddaf 100644</span><br><span>--- a/tests/test_config.c</span><br><span>+++ b/tests/test_config.c</span><br><span>@@ -1943,6 +1943,35 @@</span><br><span> </span><br><span> return AST_TEST_PASS;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(variable_list_from_string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_variable *, list, NULL, ast_variables_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_str *, str, NULL, ast_free);</span><br><span style="color: hsl(120, 100%, 40%);">+ char *parse_string;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "variable_list_from_string";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/main/config/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test parsing a string into a variable list";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = info->summary;</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</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%);">+ parse_string = "abc = 'def', ghi = 'j,kl', mno='pq=r', stu = 'vwx=\"yz\", ABC = \"DEF\"'";</span><br><span style="color: hsl(120, 100%, 40%);">+ list = ast_variable_list_from_string(parse_string, ",", "=");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, list != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ str = ast_variable_list_join(list, "|", "^", "@", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ strcmp(ast_str_buffer(str), "abc^@def@|ghi^@j,kl@|mno^@pq=r@|stu^@vwx=\"yz\", ABC = \"DEF\"@") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int unload_module(void)</span><br><span> {</span><br><span> AST_TEST_UNREGISTER(config_save);</span><br><span>@@ -1956,6 +1985,7 @@</span><br><span> AST_TEST_UNREGISTER(config_dialplan_function);</span><br><span> AST_TEST_UNREGISTER(variable_lists_match);</span><br><span> AST_TEST_UNREGISTER(variable_list_join_replace);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(variable_list_from_string);</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -1972,6 +2002,7 @@</span><br><span> AST_TEST_REGISTER(config_dialplan_function);</span><br><span> AST_TEST_REGISTER(variable_lists_match);</span><br><span> AST_TEST_REGISTER(variable_list_join_replace);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(variable_list_from_string);</span><br><span> return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18141">change 18141</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/+/18141"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I1e1d149be22165a1fb8e88e2903a36bba1a6cf2e </div>
<div style="display:none"> Gerrit-Change-Number: 18141 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-MessageType: merged </div>