<p>George Joseph <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18127">View Change</a></p><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_geolocation: eprofile, parsing, tests and more<br><br>There's a lot of stuff in this commit so hold on to<br>your knickers.<br><br>* Added ability to embed xml and xslt documents into a module.<br> It's actually quite simnple and works for gcc and clang.<br> See Makefile.rules, res/Makefile and geoloc_eprofile for<br> more info.<br><br>* Fixed an issue with ast_variable_list_from_string where<br> quotes weren't being handled correctly. This required<br> the addition of ast_strsep_strict() to utils.c<br><br>* Renamed some things...<br> pidf_lo_section was renamed to just pidf_element.<br> The "effective_profile" API names were shortened to<br> "eprofile".<br><br>* Added a ast_xml_find_child_element() convenience macro.<br><br>* Added pidf_to_eprofile.xslt that condenses pidf-lo xml<br> documents to a simpler format that's common to both GML<br> and civicAddress formats. This cut quite a bit of custom<br> parsing code.<br><br>* Effective profiles can now be created directly from a pidf<br> xml document or a URI.<br><br>* Created unit tests for effective profile creation.<br><br>Change-Id: I50b66bd041b2a62ab329406f20dbaeef1fa68fc1<br>---<br>M Makefile.rules<br>M configs/samples/geolocation.conf.sample<br>M include/asterisk/config.h<br>M include/asterisk/res_geolocation.h<br>M include/asterisk/strings.h<br>M include/asterisk/xml.h<br>M main/config.c<br>M main/utils.c<br>M res/Makefile<br>M res/res_geolocation.c<br>M res/res_geolocation/geoloc_channel.c<br>A res/res_geolocation/geoloc_common.c<br>M res/res_geolocation/geoloc_config.c<br>M res/res_geolocation/geoloc_doc.xml<br>A res/res_geolocation/geoloc_eprofile.c<br>M res/res_geolocation/geoloc_private.h<br>A res/res_geolocation/pidf_lo_test.xml<br>A res/res_geolocation/pidf_to_eprofile.xslt<br>M tests/test_config.c<br>19 files changed, 1,241 insertions(+), 132 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/Makefile.rules b/Makefile.rules</span><br><span>index 934e44a..e6b6589 100644</span><br><span>--- a/Makefile.rules</span><br><span>+++ b/Makefile.rules</span><br><span>@@ -204,4 +204,19 @@</span><br><span> $(ECHO_PREFIX) echo " [LD] $^ -> $@"</span><br><span> $(CMD_PREFIX) $(CXX) -o $@ $(PTHREAD_CFLAGS) $(_ASTLDFLAGS) $^ $(CXX_LIBS) $(ASTLDFLAGS)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+# These CC commands just create an object file with the input file embedded in it.</span><br><span style="color: hsl(120, 100%, 40%);">+# It can be access from code as follows:</span><br><span style="color: hsl(120, 100%, 40%);">+# If your input file is named abc_def.xml...</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# extern const uint8_t _binary_abc_def_xml_start[];</span><br><span style="color: hsl(120, 100%, 40%);">+# extern const uint8_t _binary_abc_def_xml_end[];</span><br><span style="color: hsl(120, 100%, 40%);">+# extern const size_t _binary_abc_def_xml_size;</span><br><span style="color: hsl(120, 100%, 40%);">+%.o: %.xml</span><br><span style="color: hsl(120, 100%, 40%);">+ $(ECHO_PREFIX) echo " [LD] $^ -> $@"</span><br><span style="color: hsl(120, 100%, 40%);">+ $(CMD_PREFIX) $(CC) -g -nostartfiles -nodefaultlibs -nostdlib -r -Wl,-b,binary -o $@ $^</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+%.o: %.xslt</span><br><span style="color: hsl(120, 100%, 40%);">+ $(ECHO_PREFIX) echo " [LD] $^ -> $@"</span><br><span style="color: hsl(120, 100%, 40%);">+ $(CMD_PREFIX) $(CC) -g -nostartfiles -nodefaultlibs -nostdlib -r -Wl,-b,binary -o $@ $^</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> dist-clean:: clean</span><br><span>diff --git a/configs/samples/geolocation.conf.sample b/configs/samples/geolocation.conf.sample</span><br><span>index f8909ec..7cf0bb5 100644</span><br><span>--- a/configs/samples/geolocation.conf.sample</span><br><span>+++ b/configs/samples/geolocation.conf.sample</span><br><span>@@ -8,9 +8,9 @@</span><br><span> 5. Reference</span><br><span> --;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-;-----------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+;--=====================================================================</span><br><span> Overview</span><br><span>------------------------------------------------------------------------;</span><br><span style="color: hsl(120, 100%, 40%);">+=====================================================================--;</span><br><span> </span><br><span> ;--</span><br><span> </span><br><span>@@ -43,9 +43,9 @@</span><br><span> being sent to an emergency response center or even call failure for</span><br><span> which you are solely responsible.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-;-----------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+;--=====================================================================</span><br><span> Location Object Description</span><br><span>------------------------------------------------------------------------;</span><br><span style="color: hsl(120, 100%, 40%);">+=====================================================================--;</span><br><span> </span><br><span> ;-- type -------------------------------------------</span><br><span> Must be "location" to identify this configuration section as a</span><br><span>@@ -224,16 +224,16 @@</span><br><span> ---------------------------------------------------;</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-;-----------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+;--=====================================================================</span><br><span> Profile Object Descriptions</span><br><span>------------------------------------------------------------------------;</span><br><span style="color: hsl(120, 100%, 40%);">+=====================================================================--;</span><br><span> </span><br><span> ;-- type -------------------------------------------</span><br><span> Must be "profile" to identify this configuration section as a</span><br><span> Geolocation Profile object.</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-;-- pidf_lo_section -------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+;-- pidf_element ----------------------------------</span><br><span> </span><br><span> If the format is civicAddress or GML, this sets the PIDF element into</span><br><span> which the location information will be placed.</span><br><span>@@ -323,9 +323,9 @@</span><br><span> ---------------------------------------------------;</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-;---------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+;--=====================================================================</span><br><span> Examples</span><br><span>----------------------------------------------------;</span><br><span style="color: hsl(120, 100%, 40%);">+=====================================================================--;</span><br><span> </span><br><span> ; Create a Location Object for a building</span><br><span> [building_1]</span><br><span>@@ -392,9 +392,9 @@</span><br><span> ; Geolocation: <https://some.company.com?building=bldg1&number=5678></span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-;-------------------------------</span><br><span>------------ REFERENCE ----------</span><br><span>--------------------------------;</span><br><span style="color: hsl(120, 100%, 40%);">+;--=====================================================================</span><br><span style="color: hsl(120, 100%, 40%);">+ REFERENCE</span><br><span style="color: hsl(120, 100%, 40%);">+=====================================================================--;</span><br><span> ;--</span><br><span> </span><br><span> [RFC4119] A Presence-based GEOPRIV Location Object Format</span><br><span>diff --git a/include/asterisk/config.h b/include/asterisk/config.h</span><br><span>index afac229..a05e126 100644</span><br><span>--- a/include/asterisk/config.h</span><br><span>+++ b/include/asterisk/config.h</span><br><span>@@ -1015,12 +1015,15 @@</span><br><span> * \param name_value_separator The string used to separate each item's name and value.</span><br><span> * Only the first character in the string will be used.</span><br><span> * If NULL, "=" will be used.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param quote_str The string used to quote values.</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> *</span><br><span> * \retval A pointer to a list of ast_variables.</span><br><span> * \retval NULL if there was an error or no variables could be parsed.</span><br><span> */</span><br><span> struct ast_variable *ast_variable_list_from_string(const char *input, const char *item_separator,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *name_value_separator);</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name_value_separator, const char *quote_str);</span><br><span> </span><br><span> /*!</span><br><span> * \brief Update variable value within a config</span><br><span>diff --git a/include/asterisk/res_geolocation.h b/include/asterisk/res_geolocation.h</span><br><span>index 6230cf2..7fae4bf 100644</span><br><span>--- a/include/asterisk/res_geolocation.h</span><br><span>+++ b/include/asterisk/res_geolocation.h</span><br><span>@@ -20,12 +20,14 @@</span><br><span> #define INCLUDE_ASTERISK_RES_GEOLOCATION_H_</span><br><span> </span><br><span> #include "asterisk/sorcery.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/config.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/xml.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-enum ast_geoloc_pidf_section {</span><br><span style="color: hsl(0, 100%, 40%);">- AST_PIDF_SECTION_NONE = 0,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_PIDF_SECTION_TUPLE,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_PIDF_SECTION_DEVICE,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_PIDF_SECTION_PERSON</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_geoloc_pidf_element {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_PIDF_ELEMENT_NONE = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_PIDF_ELEMENT_TUPLE,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_PIDF_ELEMENT_DEVICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_PIDF_ELEMENT_PERSON</span><br><span> };</span><br><span> </span><br><span> enum ast_geoloc_format {</span><br><span>@@ -44,6 +46,9 @@</span><br><span> </span><br><span> struct ast_geoloc_location {</span><br><span> SORCERY_OBJECT(details);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STRING_FIELD(method);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span> enum ast_geoloc_format format;</span><br><span> struct ast_variable *location_vars;</span><br><span> };</span><br><span>@@ -53,7 +58,7 @@</span><br><span> AST_DECLARE_STRING_FIELDS(</span><br><span> AST_STRING_FIELD(location_reference);</span><br><span> );</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_geoloc_pidf_section pidf_section;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_pidf_element pidf_element;</span><br><span> enum ast_geoloc_location_disposition location_disposition;</span><br><span> int geolocation_routing;</span><br><span> int send_location;</span><br><span>@@ -66,8 +71,9 @@</span><br><span> AST_DECLARE_STRING_FIELDS(</span><br><span> AST_STRING_FIELD(id);</span><br><span> AST_STRING_FIELD(location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STRING_FIELD(method);</span><br><span> );</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_geoloc_pidf_section pidf_section;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_pidf_element pidf_element;</span><br><span> enum ast_geoloc_location_disposition location_disposition;</span><br><span> int geolocation_routing;</span><br><span> int send_location;</span><br><span>@@ -141,8 +147,72 @@</span><br><span> enum ast_geoloc_validate_result ast_geoloc_gml_validate_varlist(const struct ast_variable *varlist,</span><br><span> const char **result);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_datastore *ast_geoloc_datastore_create(const char *profile_name);</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Create a geoloc datastore from a profile name</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param profile_name The name of the profile to use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The datastore.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_datastore *ast_geoloc_datastore_create_from_profile_name(const char *profile_name);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_geoloc_effective_profile *ast_geoloc_effective_profile_create(struct ast_geoloc_profile *profile);</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Create a geoloc datastore from an effective profile.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param eprofile The effective profile to use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The datastore.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_datastore *ast_geoloc_datastore_create_from_eprofile(</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile);</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 Allocate a new, empty effective profile.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param name The profile's name</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The effective profile ao2 object.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_geoloc_effective_profile *ast_geoloc_eprofile_alloc(const char *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 Allocate a new effective profile from an existing profile.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param profile The profile to use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The effective profile ao2 object.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_geoloc_effective_profile *ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile);</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 Allocate a new effective profile from an XML PIDF-LO document</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param pidf_xmldoc The ast_xml_doc to use.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param reference_string An identifying string to use in error messages.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The effective profile ao2 object.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_geoloc_effective_profile *ast_geoloc_eprofile_create_from_pidf(</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_doc *pidf_xmldoc, const char *reference_string);</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 Allocate a new effective profile from a URI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uri The URI to use.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param reference_string An identifying string to use in error messages.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The effective profile ao2 object.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_geoloc_effective_profile *ast_geoloc_eprofile_create_from_uri(const char *uri,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *reference_string);</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 Refresh the effective profile with any changed info.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param eprofile The eprofile to refresh.</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 error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_geoloc_eprofile_refresh_location(struct ast_geoloc_effective_profile *eprofile);</span><br><span> </span><br><span> #endif /* INCLUDE_ASTERISK_RES_GEOLOCATION_H_ */</span><br><span>diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h</span><br><span>index ab46273..5c14f4a 100644</span><br><span>--- a/include/asterisk/strings.h</span><br><span>+++ b/include/asterisk/strings.h</span><br><span>@@ -308,6 +308,8 @@</span><br><span> */</span><br><span> char *ast_strsep(char **s, const char sep, uint32_t flags);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *ast_strsep_strict(char **s, const char sep, const char quote, uint32_t flags);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span> \brief Strip backslash for "escaped" semicolons,</span><br><span> the string to be stripped (will be modified).</span><br><span>diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h</span><br><span>index 9d43560..5564051 100644</span><br><span>--- a/include/asterisk/xml.h</span><br><span>+++ b/include/asterisk/xml.h</span><br><span>@@ -189,6 +189,18 @@</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> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Find a direct child element by name.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param parent_node This is the parent node to search.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param name Node name to find.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param attrname attribute name to match (if NULL it won't be matched).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param attrvalue attribute value to match (if NULL it won't be matched).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL if not found.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return The node on success.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ast_xml_find_child_element(_parent_node, _name, _attrname, _attrvalue) \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_xml_find_element(ast_xml_node_get_children(_parent_node), _name, _attrname, _attrvalue)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Get the prefix of a namespace.</span><br><span> * \param ns The namespace</span><br><span> * \return The prefix of the namespace.</span><br><span>diff --git a/main/config.c b/main/config.c</span><br><span>index 122e7aa..07925bd 100644</span><br><span>--- a/main/config.c</span><br><span>+++ b/main/config.c</span><br><span>@@ -723,10 +723,11 @@</span><br><span> }</span><br><span> </span><br><span> struct ast_variable *ast_variable_list_from_string(const char *input, const char *item_separator,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *name_value_separator)</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name_value_separator, const char *quote_str)</span><br><span> {</span><br><span> char item_sep;</span><br><span> char nv_sep;</span><br><span style="color: hsl(120, 100%, 40%);">+ char quote;</span><br><span> struct ast_variable *new_list = NULL;</span><br><span> struct ast_variable *new_var = NULL;</span><br><span> char *item_string;</span><br><span>@@ -740,11 +741,14 @@</span><br><span> </span><br><span> item_sep = ast_strlen_zero(item_separator) ? ',' : item_separator[0];</span><br><span> nv_sep = ast_strlen_zero(name_value_separator) ? '=' : name_value_separator[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ quote = ast_strlen_zero(quote_str) ? '"' : quote_str[0];</span><br><span> item_string = ast_strip(ast_strdupa(input));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- while ((item = ast_strsep(&item_string, item_sep, AST_STRSEP_ALL))) {</span><br><span style="color: hsl(0, 100%, 40%);">- item_name = ast_strsep(&item, nv_sep, AST_STRSEP_ALL);</span><br><span style="color: hsl(0, 100%, 40%);">- item_value = ast_strsep(&item, nv_sep, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((item = ast_strsep_strict(&item_string, item_sep, quote, AST_STRSEP_ALL))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ item_name = ast_strsep_strict(&item, nv_sep, quote, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ item_value = ast_strsep_strict(&item, nv_sep, quote, AST_STRSEP_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> new_var = ast_variable_new(item_name, item_value, "");</span><br><span> if (!new_var) {</span><br><span> ast_variables_destroy(new_list);</span><br><span>diff --git a/main/utils.c b/main/utils.c</span><br><span>index 29676fa..38c5b0c 100644</span><br><span>--- a/main/utils.c</span><br><span>+++ b/main/utils.c</span><br><span>@@ -1859,6 +1859,67 @@</span><br><span> return st;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *ast_strsep_strict(char **iss, const char sep, const char quote, uint32_t flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *st = *iss;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *is;</span><br><span style="color: hsl(120, 100%, 40%);">+ int inquote = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int found = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ char stack[8];</span><br><span style="color: hsl(120, 100%, 40%);">+ const char qstr[] = { quote };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(st)) {</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%);">+ memset(stack, 0, sizeof(stack));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for(is = st; *is; is++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*is == '\\') {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*++is != '\0') {</span><br><span style="color: hsl(120, 100%, 40%);">+ is++;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</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 (*is == quote) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*is == stack[inquote]) {</span><br><span style="color: hsl(120, 100%, 40%);">+ stack[inquote--] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (++inquote >= sizeof(stack)) {</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%);">+ stack[inquote] = *is;</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 (*is == sep && !inquote) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *is = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ found = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ *iss = is + 1;</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%);">+ if (!found) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *iss = 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 (flags & AST_STRSEP_STRIP) {</span><br><span style="color: hsl(120, 100%, 40%);">+ st = ast_strip_quoted(st, qstr, qstr);</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 (flags & AST_STRSEP_TRIM) {</span><br><span style="color: hsl(120, 100%, 40%);">+ st = ast_strip(st);</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 (flags & AST_STRSEP_UNESCAPE) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_unescape_quoted(st);</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 st;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> char *ast_unescape_semicolon(char *s)</span><br><span> {</span><br><span> char *e;</span><br><span>diff --git a/res/Makefile b/res/Makefile</span><br><span>index a6dd181..6abdd2d 100644</span><br><span>--- a/res/Makefile</span><br><span>+++ b/res/Makefile</span><br><span>@@ -69,9 +69,13 @@</span><br><span> $(call MOD_ADD_C,res_stir_shaken,$(wildcard res_stir_shaken/*.c))</span><br><span> $(call MOD_ADD_C,res_geolocation,$(wildcard res_geolocation/*.c))</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+# These are the xml and xslt files to be embedded</span><br><span style="color: hsl(120, 100%, 40%);">+res_geolocation.so: res_geolocation/pidf_lo_test.o res_geolocation/pidf_to_eprofile.o</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> res_parking.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)</span><br><span> snmp/agent.o: _ASTCFLAGS+=-fPIC</span><br><span> res_snmp.o: _ASTCFLAGS+=-fPIC</span><br><span> </span><br><span> # Dependencies for res_ari_*.so are generated, so they're in this file</span><br><span> include ari.make</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/res/res_geolocation.c b/res/res_geolocation.c</span><br><span>index 09a9a4b..9108102 100644</span><br><span>--- a/res/res_geolocation.c</span><br><span>+++ b/res/res_geolocation.c</span><br><span>@@ -17,6 +17,8 @@</span><br><span> */</span><br><span> </span><br><span> /*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+ <depend>libxml2</depend></span><br><span style="color: hsl(120, 100%, 40%);">+ <depend>libxslt</depend></span><br><span> <support_level>core</support_level></span><br><span> ***/</span><br><span> </span><br><span>@@ -24,21 +26,6 @@</span><br><span> #include "asterisk.h"</span><br><span> #include "res_geolocation/geoloc_private.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const char *result_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">- "Success",</span><br><span style="color: hsl(0, 100%, 40%);">- "Missing type",</span><br><span style="color: hsl(0, 100%, 40%);">- "Invalid shape type",</span><br><span style="color: hsl(0, 100%, 40%);">- "Invalid variable name",</span><br><span style="color: hsl(0, 100%, 40%);">- "Not enough variables",</span><br><span style="color: hsl(0, 100%, 40%);">- "Too many variables",</span><br><span style="color: hsl(0, 100%, 40%);">- "Invalid variable value"</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-const char *ast_geoloc_validate_result_to_str(enum ast_geoloc_validate_result result)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return result_names[result];</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static int reload_module(void)</span><br><span> {</span><br><span> int res = 0;</span><br><span>@@ -55,6 +42,10 @@</span><br><span> if (res) {</span><br><span> return AST_MODULE_LOAD_DECLINE;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+ res = geoloc_eprofile_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> res = geoloc_dialplan_reload();</span><br><span> if (res) {</span><br><span> return AST_MODULE_LOAD_DECLINE;</span><br><span>@@ -71,8 +62,9 @@</span><br><span> {</span><br><span> int res = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- res += geoloc_channel_reload();</span><br><span style="color: hsl(120, 100%, 40%);">+ res += geoloc_channel_unload();</span><br><span> res += geoloc_dialplan_unload();</span><br><span style="color: hsl(120, 100%, 40%);">+ res += geoloc_eprofile_unload();</span><br><span> res += geoloc_config_unload();</span><br><span> res += geoloc_gml_unload();</span><br><span> res += geoloc_civicaddr_unload();</span><br><span>@@ -84,23 +76,29 @@</span><br><span> {</span><br><span> int res = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- res = geoloc_gml_load();</span><br><span style="color: hsl(0, 100%, 40%);">- if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">- return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> res = geoloc_civicaddr_load();</span><br><span> if (res) {</span><br><span> unload_module();</span><br><span> return AST_MODULE_LOAD_DECLINE;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ res = geoloc_gml_load();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> res = geoloc_config_load();</span><br><span> if (res) {</span><br><span> unload_module();</span><br><span> return AST_MODULE_LOAD_DECLINE;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ res = geoloc_eprofile_load();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ unload_module();</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> res = geoloc_dialplan_load();</span><br><span> if (res) {</span><br><span> unload_module();</span><br><span>diff --git a/res/res_geolocation/geoloc_channel.c b/res/res_geolocation/geoloc_channel.c</span><br><span>index 719e214..aa8ad87 100644</span><br><span>--- a/res/res_geolocation/geoloc_channel.c</span><br><span>+++ b/res/res_geolocation/geoloc_channel.c</span><br><span>@@ -18,6 +18,7 @@</span><br><span> </span><br><span> #include "asterisk.h"</span><br><span> #include "asterisk/datastore.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/res_geolocation.h"</span><br><span> #include "geoloc_private.h"</span><br><span> </span><br><span> </span><br><span>@@ -36,7 +37,7 @@</span><br><span> };</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_datastore *ast_geoloc_datastore_create(const char *profile_name)</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_datastore *ast_geoloc_datastore_create_from_profile_name(const char *profile_name)</span><br><span> {</span><br><span> struct ast_datastore *ds = NULL;</span><br><span> struct ast_geoloc_effective_profile *eprofile = NULL;</span><br><span>@@ -59,7 +60,7 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- eprofile = ast_geoloc_effective_profile_create(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = ast_geoloc_eprofile_create_from_profile(profile);</span><br><span> ao2_ref(profile, -1);</span><br><span> if (!eprofile) {</span><br><span> ast_datastore_free(ds);</span><br><span>diff --git a/res/res_geolocation/geoloc_common.c b/res/res_geolocation/geoloc_common.c</span><br><span>new file mode 100644</span><br><span>index 0000000..bb24a31</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_common.c</span><br><span>@@ -0,0 +1,36 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2022, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *result_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ "Success",</span><br><span style="color: hsl(120, 100%, 40%);">+ "Missing type",</span><br><span style="color: hsl(120, 100%, 40%);">+ "Invalid shape type",</span><br><span style="color: hsl(120, 100%, 40%);">+ "Invalid variable name",</span><br><span style="color: hsl(120, 100%, 40%);">+ "Not enough variables",</span><br><span style="color: hsl(120, 100%, 40%);">+ "Too many variables",</span><br><span style="color: hsl(120, 100%, 40%);">+ "Invalid variable value"</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%);">+const char *ast_geoloc_validate_result_to_str(enum ast_geoloc_validate_result result)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return result_names[result];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/res/res_geolocation/geoloc_config.c b/res/res_geolocation/geoloc_config.c</span><br><span>index c2fa2d0..b707c89 100644</span><br><span>--- a/res/res_geolocation/geoloc_config.c</span><br><span>+++ b/res/res_geolocation/geoloc_config.c</span><br><span>@@ -24,7 +24,7 @@</span><br><span> </span><br><span> static struct ast_sorcery *geoloc_sorcery;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const char *pidf_section_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *pidf_element_names[] = {</span><br><span> "<none>",</span><br><span> "tuple",</span><br><span> "device",</span><br><span>@@ -51,16 +51,22 @@</span><br><span> static void geoloc_location_destructor(void *obj) {</span><br><span> struct ast_geoloc_location *location = obj;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_free_memory(location);</span><br><span> ast_variables_destroy(location->location_vars);</span><br><span> }</span><br><span> </span><br><span> static void *geoloc_location_alloc(const char *name)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_sorcery_generic_alloc(sizeof(struct ast_geoloc_location), geoloc_location_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_location *location = ast_sorcery_generic_alloc(sizeof(struct ast_geoloc_location), geoloc_location_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (location) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_init(location, 128);</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 location;</span><br><span> }</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_ENUM(profile, pidf_section)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_ENUM(profile, pidf_element)</span><br><span> CONFIG_ENUM(profile, location_disposition)</span><br><span> CONFIG_VAR_LIST(profile, location_refinement)</span><br><span> CONFIG_VAR_LIST(profile, location_variables)</span><br><span>@@ -86,77 +92,6 @@</span><br><span> return profile;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void geoloc_effective_profile_destructor(void *obj) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_geoloc_effective_profile *eprofile = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_free_memory(eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->location_refinement);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->location_variables);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variables_destroy(eprofile->usage_rules_vars);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void *geoloc_effective_profile_alloc(const char *name)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_geoloc_effective_profile *eprofile = ao2_alloc_options(sizeof(*eprofile),</span><br><span style="color: hsl(0, 100%, 40%);">- geoloc_effective_profile_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_init(eprofile, 256);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(eprofile, id, name);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return eprofile;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_geoloc_effective_profile *ast_geoloc_effective_profile_create(struct ast_geoloc_profile *profile)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_geoloc_effective_profile *eprofile;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *profile_id;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_geoloc_location *loc = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!profile) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- profile_id = ast_sorcery_object_get_id(profile);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile = geoloc_effective_profile_alloc(profile_id);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_lock(profile);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(eprofile, location_reference, profile->location_reference);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->geolocation_routing = profile->geolocation_routing;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->pidf_section = profile->pidf_section;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_refinement = profile->location_refinement ? ast_variables_dup(profile->location_refinement) : NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_variables = profile->location_variables ? ast_variables_dup(profile->location_variables) : NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->usage_rules_vars = profile->usage_rules_vars ? ast_variables_dup(profile->usage_rules_vars) : NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_disposition = profile->location_disposition;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->send_location = profile->send_location;</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_unlock(profile);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span style="color: hsl(0, 100%, 40%);">- loc = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", eprofile->location_reference);</span><br><span style="color: hsl(0, 100%, 40%);">- if (loc) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *var;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->format = loc->format;</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_vars = ast_variables_dup(loc->location_vars);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(loc, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->effective_location = ast_variables_dup(loc->location_vars);</span><br><span style="color: hsl(0, 100%, 40%);">- for (var = profile->location_refinement; var; var = var->next) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *newvar = ast_variable_new(var->name, var->value, "");</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_variable_list_replace(&eprofile->effective_location, newvar)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_variable_list_append(&eprofile->effective_location, newvar);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Profile '%s' referenced location '%s' does not exist!", profile_id,</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->location_reference);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return eprofile;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static int geoloc_location_apply_handler(const struct ast_sorcery *sorcery, void *obj)</span><br><span> {</span><br><span> struct ast_geoloc_location *location = obj;</span><br><span>@@ -498,7 +433,7 @@</span><br><span> struct ast_str *refinement_str = NULL;</span><br><span> struct ast_str *variables_str = NULL;</span><br><span> struct ast_str *resolved_str = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_geoloc_effective_profile *eprofile = ast_geoloc_effective_profile_create(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile = ast_geoloc_eprofile_create_from_profile(profile);</span><br><span> ao2_ref(profile, -1);</span><br><span> </span><br><span> if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span>@@ -515,7 +450,7 @@</span><br><span> "id: %-s\n"</span><br><span> "received_location_disposition: %-s\n"</span><br><span> "send_location: %-s\n"</span><br><span style="color: hsl(0, 100%, 40%);">- "pidf_section: %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "pidf_element: %-s\n"</span><br><span> "location_reference: %-s\n"</span><br><span> "Location_format: %-s\n"</span><br><span> "location_reference_details: %-s\n"</span><br><span>@@ -525,7 +460,7 @@</span><br><span> eprofile->id,</span><br><span> disposition,</span><br><span> eprofile->send_location ? "yes" : "no",</span><br><span style="color: hsl(0, 100%, 40%);">- pidf_section_names[eprofile->pidf_section],</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_element_names[eprofile->pidf_element],</span><br><span> S_OR(eprofile->location_reference, "<none>"),</span><br><span> format_names[eprofile->format],</span><br><span> S_COR(loc_str, ast_str_buffer(loc_str), "<none>"),</span><br><span>@@ -591,6 +526,9 @@</span><br><span> {</span><br><span> ast_cli_unregister_multiple(geoloc_location_cli_commands, ARRAY_LEN(geoloc_location_cli_commands));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_unregister(geoloc_sorcery, "profile");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_unregister(geoloc_sorcery, "location");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (geoloc_sorcery) {</span><br><span> ast_sorcery_unref(geoloc_sorcery);</span><br><span> }</span><br><span>@@ -629,8 +567,8 @@</span><br><span> }</span><br><span> </span><br><span> ast_sorcery_object_field_register(geoloc_sorcery, "profile", "type", "", OPT_NOOP_T, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "pidf_lo_section", AST_PIDF_SECTION_NONE,</span><br><span style="color: hsl(0, 100%, 40%);">- pidf_section_handler, pidf_section_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "pidf_element", AST_PIDF_ELEMENT_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_element_handler, pidf_element_to_str, NULL, 0, 0);</span><br><span> ast_sorcery_object_field_register(geoloc_sorcery, "profile", "location_reference", "", OPT_STRINGFIELD_T,</span><br><span> 0, STRFLDSET(struct ast_geoloc_profile, location_reference));</span><br><span> ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "received_location_disposition", "discard",</span><br><span>diff --git a/res/res_geolocation/geoloc_doc.xml b/res/res_geolocation/geoloc_doc.xml</span><br><span>index 36bfa3c..8322585 100644</span><br><span>--- a/res/res_geolocation/geoloc_doc.xml</span><br><span>+++ b/res/res_geolocation/geoloc_doc.xml</span><br><span>@@ -57,7 +57,7 @@</span><br><span> <configOption name="type"></span><br><span> <synopsis>Must be of type 'profile'.</synopsis></span><br><span> </configOption></span><br><span style="color: hsl(0, 100%, 40%);">- <configOption name="pidf_lo_section" default="device"></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="pidf_element" default="device"></span><br><span> <synopsis>PIDF-LO element to place this profile in</synopsis></span><br><span> <description></span><br><span> <enumlist></span><br><span>diff --git a/res/res_geolocation/geoloc_eprofile.c b/res/res_geolocation/geoloc_eprofile.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b6641c7</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/geoloc_eprofile.c</span><br><span>@@ -0,0 +1,503 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2022, Sangoma Technologies Corporation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * George Joseph <gjoseph@sangoma.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</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%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/xml.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "geoloc_private.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern const uint8_t _binary_res_geolocation_pidf_to_eprofile_xslt_start[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const uint8_t _binary_res_geolocation_pidf_to_eprofile_xslt_end[];</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t pidf_to_eprofile_xslt_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern const uint8_t _binary_res_geolocation_pidf_lo_test_xml_start[];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const uint8_t _binary_res_geolocation_pidf_lo_test_xml_end[];</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t pidf_lo_test_xml_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_xslt_doc *pidf_lo_xslt;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_sorcery *geoloc_sorcery;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void geoloc_effective_profile_destructor(void *obj) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_free_memory(eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->location_refinement);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->location_variables);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->usage_rules_vars);</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_geoloc_effective_profile *ast_geoloc_eprofile_alloc(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile = ao2_alloc_options(sizeof(*eprofile),</span><br><span style="color: hsl(120, 100%, 40%);">+ geoloc_effective_profile_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_init(eprofile, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(eprofile, id, name); /* SAFE string fields handle NULL */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return eprofile;</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_geoloc_eprofile_refresh_location(struct ast_geoloc_effective_profile *eprofile)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_location *loc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(eprofile->location_reference)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ loc = ast_sorcery_retrieve_by_id(geoloc_sorcery, "location", eprofile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!loc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Profile '%s' referenced location '%s' does not exist!", eprofile->id,</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -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%);">+ eprofile->format = loc->format;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variables_destroy(eprofile->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_vars = ast_variables_dup(loc->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(loc, -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%);">+ ast_variables_destroy(eprofile->effective_location);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->effective_location = ast_variables_dup(eprofile->location_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (eprofile->location_refinement) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (var = eprofile->location_refinement; var; var = var->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *newvar = ast_variable_new(var->name, var->value, "");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_variable_list_replace(&eprofile->effective_location, newvar)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variable_list_append(&eprofile->effective_location, newvar);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</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%);">+#define DUP_VARS(_dest, _source) \</span><br><span style="color: hsl(120, 100%, 40%);">+({ \</span><br><span style="color: hsl(120, 100%, 40%);">+ int _rc = 0; \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (_source) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *_vars = ast_variables_dup(_source); \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!_vars) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ _rc = -1; \</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { \</span><br><span style="color: hsl(120, 100%, 40%);">+ _dest = _vars; \</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%);">+ (_rc); \</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_geoloc_effective_profile *ast_geoloc_eprofile_create_from_profile(struct ast_geoloc_profile *profile)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *profile_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!profile) {</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%);">+ profile_id = ast_sorcery_object_get_id(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = ast_geoloc_eprofile_alloc(profile_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile) {</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%);">+ ao2_lock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(eprofile, location_reference, profile->location_reference);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->geolocation_routing = profile->geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->pidf_element = profile->pidf_element;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = DUP_VARS(eprofile->location_refinement, profile->location_refinement);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = DUP_VARS(eprofile->location_variables, profile->location_variables);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = DUP_VARS(eprofile->usage_rules_vars, profile->usage_rules_vars);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_unlock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(eprofile, -1);</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%);">+ eprofile->location_disposition = profile->location_disposition;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->send_location = profile->send_location;</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_unlock(profile);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_geoloc_eprofile_refresh_location(eprofile) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(eprofile, -1);</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 eprofile;</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_geoloc_effective_profile *ast_geoloc_eprofile_create_from_uri(const char *uri,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *reference_string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *local_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(uri)) {</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%);">+ local_uri = ast_strdupa(uri);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (local_uri[0] == '<') {</span><br><span style="color: hsl(120, 100%, 40%);">+ local_uri++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_ends_with(local_uri, ">")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ local_uri[strlen(local_uri)-1] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_strip(local_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = ast_geoloc_eprofile_alloc(local_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile) {</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%);">+ eprofile->format = AST_GEOLOC_FORMAT_URI;</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_vars = ast_variable_new("URI", local_uri, "");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return eprofile;</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_geoloc_effective_profile *geoloc_eprofile_create_from_xslt_result(</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_doc *result_doc,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *reference_string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_node *presence = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_node *pidf_element = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_node *location_info = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_node *usage_rules = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_node *method = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *id;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *format_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *pidf_element_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *location_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *usage_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *method_str;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *duped;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ presence = ast_xml_get_root(result_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_element = ast_xml_node_get_children(presence);</span><br><span style="color: hsl(120, 100%, 40%);">+ location_info = ast_xml_find_child_element(pidf_element, "location-info", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ usage_rules = ast_xml_find_child_element(pidf_element, "usage-rules", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ method = ast_xml_find_child_element(pidf_element, "method", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ id = S_OR(ast_xml_get_attribute(pidf_element, "id"), ast_xml_get_attribute(presence, "entity"));</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = ast_geoloc_eprofile_alloc(id);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile) {</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%);">+ format_str = ast_xml_get_attribute(location_info, "format");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strings_equal(format_str, "gml")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->format = AST_GEOLOC_FORMAT_GML;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(format_str, "civicAddress")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->format = AST_GEOLOC_FORMAT_CIVIC_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(eprofile, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Unknown format '%s'\n", reference_string, format_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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_element_str = ast_xml_get_attribute(pidf_element, "name");</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->pidf_element = geoloc_pidf_element_str_to_enum(pidf_element_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ location_str = ast_xml_get_text(location_info);</span><br><span style="color: hsl(120, 100%, 40%);">+ duped = ast_strdupa(location_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->location_vars = ast_variable_list_from_string(duped, ",", "=", "\"");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!eprofile->location_vars) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(eprofile, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "%s: Unable to create location variables from '%s'\n", reference_string, location_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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ usage_str = ast_xml_get_text(usage_rules);</span><br><span style="color: hsl(120, 100%, 40%);">+ duped = ast_strdupa(usage_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->usage_rules_vars = ast_variable_list_from_string(duped, ",", "=", "\"");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ method_str = ast_xml_get_text(method);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(eprofile, method, method_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return eprofile;</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_geoloc_effective_profile *ast_geoloc_eprofile_create_from_pidf(</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_doc *pidf_xmldoc, const char *reference_string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_xml_doc *, result_doc, NULL, ast_xml_close);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_effective_profile *eprofile;</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%);">+ * The namespace prefixes used here (dm, def, gp, etc) don't have to match</span><br><span style="color: hsl(120, 100%, 40%);">+ * the ones used in the received PIDF-LO document but they MUST match the</span><br><span style="color: hsl(120, 100%, 40%);">+ * ones in the embedded pidf_to_eprofile stylesheet.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * RFC5491 Rule 8 states that...</span><br><span style="color: hsl(120, 100%, 40%);">+ * Where a PIDF document contains more than one <geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ * element, the priority of interpretation is given to the first</span><br><span style="color: hsl(120, 100%, 40%);">+ * <device> element in the document containing a location. If no</span><br><span style="color: hsl(120, 100%, 40%);">+ * <device> element containing a location is present in the document,</span><br><span style="color: hsl(120, 100%, 40%);">+ * then priority is given to the first <tuple> element containing a</span><br><span style="color: hsl(120, 100%, 40%);">+ * location. Locations contained in <person> tuples SHOULD only be</span><br><span style="color: hsl(120, 100%, 40%);">+ * used as a last resort.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Reminder: xpath arrays are 1-based not 0-based.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *find_device[] = { "path", "/def:presence/dm:device[.//gp:location-info][1]", NULL};</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *find_tuple[] = { "path", "/def:presence/def:tuple[.//gp:location-info][1]", NULL};</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *find_person[] = { "path", "/def:presence/dm:person[.//gp:location-info][1]", NULL};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ result_doc = ast_xslt_apply(pidf_lo_xslt, pidf_xmldoc, find_device);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!result_doc || !ast_xml_node_get_children((struct ast_xml_node *)result_doc)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_xml_close(result_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+ result_doc = ast_xslt_apply(pidf_lo_xslt, pidf_xmldoc, find_tuple);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!result_doc || !ast_xml_node_get_children((struct ast_xml_node *)result_doc)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_xml_close(result_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+ result_doc = ast_xslt_apply(pidf_lo_xslt, pidf_xmldoc, find_person);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!result_doc || !ast_xml_node_get_children((struct ast_xml_node *)result_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%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * The document returned from the stylesheet application looks like this...</span><br><span style="color: hsl(120, 100%, 40%);">+ * <presence id="presence-entity"></span><br><span style="color: hsl(120, 100%, 40%);">+ * <pidf-element name="tuple" id="element-id"></span><br><span style="color: hsl(120, 100%, 40%);">+ * <location-info format="gml">format="gml", type="Ellipsoid", crs="3d", ...</location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ * <usage-rules>retransmission-allowed="no", retention-expiry="2010-11-14T20:00:00Z"</usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ * <method>Hybrid_A-GPS</method></span><br><span style="color: hsl(120, 100%, 40%);">+ * </pidf-element></span><br><span style="color: hsl(120, 100%, 40%);">+ * </presence></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Regardless of whether the pidf-element was tuple, device or person and whether</span><br><span style="color: hsl(120, 100%, 40%);">+ * the format is gml or civicAddress, the presence, pidf-element, location-info,</span><br><span style="color: hsl(120, 100%, 40%);">+ * usage-rules and method elements should be there although usage-rules and method</span><br><span style="color: hsl(120, 100%, 40%);">+ * may be empty.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The contents of the location-info and usage-rules elements can be passed directly to</span><br><span style="color: hsl(120, 100%, 40%);">+ * ast_variable_list_from_string().</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%);">+ eprofile = geoloc_eprofile_create_from_xslt_result(result_doc, reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return eprofile;</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 TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+static void load_tests(void);</span><br><span style="color: hsl(120, 100%, 40%);">+static void unload_tests(void);</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span style="color: hsl(120, 100%, 40%);">+static void load_tests(void) {}</span><br><span style="color: hsl(120, 100%, 40%);">+static void unload_tests(void) {}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</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 geoloc_eprofile_unload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unload_tests();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pidf_lo_xslt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_xslt_close(pidf_lo_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%);">+ if (geoloc_sorcery) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_unref(geoloc_sorcery);</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 AST_MODULE_LOAD_SUCCESS;</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 geoloc_eprofile_load(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ geoloc_sorcery = geoloc_get_sorcery();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_to_eprofile_xslt_size =</span><br><span style="color: hsl(120, 100%, 40%);">+ (_binary_res_geolocation_pidf_to_eprofile_xslt_end - _binary_res_geolocation_pidf_to_eprofile_xslt_start);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_lo_test_xml_size =</span><br><span style="color: hsl(120, 100%, 40%);">+ (_binary_res_geolocation_pidf_lo_test_xml_end - _binary_res_geolocation_pidf_lo_test_xml_start);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ pidf_lo_xslt = ast_xslt_read_memory(</span><br><span style="color: hsl(120, 100%, 40%);">+ (char *)_binary_res_geolocation_pidf_to_eprofile_xslt_start, pidf_to_eprofile_xslt_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pidf_lo_xslt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unable to read pidf_lo_xslt from memory\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</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%);">+ load_tests();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_SUCCESS;</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 geoloc_eprofile_reload(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_SUCCESS;</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%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/test.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_create_from_uri)</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%);">+ RAII_VAR(struct ast_geoloc_effective_profile *, eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = AST_TEST_PASS;</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 = "create_from_uri";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/geoloc/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test create from uri";</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%);">+ eprofile = ast_geoloc_eprofile_create_from_uri("http://some_uri&a=b", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, eprofile != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, eprofile->format == AST_GEOLOC_FORMAT_URI);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, eprofile->location_vars != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ uri = ast_variable_find_in_list(eprofile->location_vars, "URI");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, uri != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, strcmp(uri, "http://some_uri&a=b") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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 enum ast_test_result_state validate_eprofile(struct ast_test *test,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_doc * pidf_xmldoc,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *path,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *id,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_pidf_element pidf_element,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_geoloc_format format,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *method,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *location,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *usage</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%);">+ RAII_VAR(struct ast_str *, str, NULL, ast_free);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_geoloc_effective_profile *, eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_xml_doc *, result_doc, NULL, ast_xml_close);</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *search[] = { "path", path, NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(path)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ result_doc = ast_xslt_apply(pidf_lo_xslt, pidf_xmldoc, (const char **)search);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, (result_doc && ast_xml_node_get_children((struct ast_xml_node *)result_doc)));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = geoloc_eprofile_create_from_xslt_result(result_doc, "test_create_from_xslt");</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile = ast_geoloc_eprofile_create_from_pidf(pidf_xmldoc, "test_create_from_pidf");</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_test_validate(test, eprofile != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "ID: '%s' pidf_element: '%s' format: '%s' method: '%s'\n", eprofile->id,</span><br><span style="color: hsl(120, 100%, 40%);">+ geoloc_pidf_element_to_name(eprofile->pidf_element),</span><br><span style="color: hsl(120, 100%, 40%);">+ geoloc_format_to_name(eprofile->format),</span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->method);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, ast_strings_equal(eprofile->id, id));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, eprofile->pidf_element == pidf_element);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, eprofile->format == format);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, ast_strings_equal(eprofile->method, method));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ str = ast_variable_list_join(eprofile->location_vars, ",", "=", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, str != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "location_vars: %s\n", ast_str_buffer(str));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, ast_strings_equal(ast_str_buffer(str), location));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ str = ast_variable_list_join(eprofile->usage_rules_vars, ",", "=", "'", NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, str != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "usage_rules: %s\n", ast_str_buffer(str));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, ast_strings_equal(ast_str_buffer(str), usage));</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 style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_create_from_pidf)</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%);">+ RAII_VAR(struct ast_xml_doc *, pidf_xmldoc, NULL, ast_xml_close);</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_test_result_state res = AST_TEST_PASS;</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 = "create_from_pidf";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/geoloc/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test create from pidf scenarios";</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%);">+ pidf_xmldoc = ast_xml_read_memory((char *)_binary_res_geolocation_pidf_lo_test_xml_start, pidf_lo_test_xml_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, pidf_xmldoc != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = validate_eprofile(test, pidf_xmldoc,</span><br><span style="color: hsl(120, 100%, 40%);">+ NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ "arcband-2d",</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_PIDF_ELEMENT_DEVICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_FORMAT_GML,</span><br><span style="color: hsl(120, 100%, 40%);">+ "TA-NMR",</span><br><span style="color: hsl(120, 100%, 40%);">+ "format=gml,type=ArcBand,crs=2d,pos=-43.5723 153.21760,innerRadius=3594,"</span><br><span style="color: hsl(120, 100%, 40%);">+ "outerRadius=4148,startAngle=20,startAngle_uom=radians,openingAngle=20,"</span><br><span style="color: hsl(120, 100%, 40%);">+ "openingAngle_uom=radians",</span><br><span style="color: hsl(120, 100%, 40%);">+ "retransmission-allowed='yes',ruleset-preference='https:/www/more.com',"</span><br><span style="color: hsl(120, 100%, 40%);">+ "retention-expires='2007-06-22T20:57:29Z'"</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, res == AST_TEST_PASS);</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 = validate_eprofile(test, pidf_xmldoc,</span><br><span style="color: hsl(120, 100%, 40%);">+ "/def:presence/dm:device[.//ca:civicAddress][1]",</span><br><span style="color: hsl(120, 100%, 40%);">+ "pres:alice@asterisk.org",</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_PIDF_ELEMENT_DEVICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_GEOLOC_FORMAT_CIVIC_ADDRESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ "GPS",</span><br><span style="color: hsl(120, 100%, 40%);">+ "format=civicAddress,country=AU,A1=NSW,A3=Wollongong,A4=North Wollongong,"</span><br><span style="color: hsl(120, 100%, 40%);">+ "RD=Flinders,STS=Street,RDBR=Campbell Street,LMK=Gilligan's Island,"</span><br><span style="color: hsl(120, 100%, 40%);">+ "LOC=Corner,NAM=Video Rental Store,PC=2500,ROOM=Westerns and Classics,"</span><br><span style="color: hsl(120, 100%, 40%);">+ "PLC=store,POBOX=Private Box 15",</span><br><span style="color: hsl(120, 100%, 40%);">+ "retransmission-allowed='yes',ruleset-preference='https:/www/more.com',"</span><br><span style="color: hsl(120, 100%, 40%);">+ "retention-expires='2007-06-22T20:57:29Z'"</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, res == AST_TEST_PASS);</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 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%);">+static void load_tests(void) {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(test_create_from_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(test_create_from_pidf);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+static void unload_tests(void) {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(test_create_from_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(test_create_from_pidf);</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</span><br><span>diff --git a/res/res_geolocation/geoloc_private.h b/res/res_geolocation/geoloc_private.h</span><br><span>index 194d507..c5ea981 100644</span><br><span>--- a/res/res_geolocation/geoloc_private.h</span><br><span>+++ b/res/res_geolocation/geoloc_private.h</span><br><span>@@ -25,8 +25,18 @@</span><br><span> #include "asterisk/lock.h"</span><br><span> #include "asterisk/res_geolocation.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define CONFIG_STR_TO_ENUM_DECL(_stem) int geoloc_ ## _stem ## _str_to_enum(const char *str);</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_STR_TO_ENUM_DECL(pidf_element)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_STR_TO_ENUM_DECL(format);</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_STR_TO_ENUM_DECL(location_disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+#define GEOLOC_ENUM_TO_NAME_DECL(_stem) const char * geoloc_ ## _stem ## _to_name(int ix);</span><br><span style="color: hsl(120, 100%, 40%);">+GEOLOC_ENUM_TO_NAME_DECL(pidf_element)</span><br><span style="color: hsl(120, 100%, 40%);">+GEOLOC_ENUM_TO_NAME_DECL(format);</span><br><span style="color: hsl(120, 100%, 40%);">+GEOLOC_ENUM_TO_NAME_DECL(location_disposition);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define CONFIG_STR_TO_ENUM(_stem) \</span><br><span style="color: hsl(0, 100%, 40%);">-static int _stem ## _str_to_enum(const char *str) \</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_ ## _stem ## _str_to_enum(const char *str) \</span><br><span> { \</span><br><span> int i; \</span><br><span> for (i = 0; i < ARRAY_LEN(_stem ## _names); i++) { \</span><br><span>@@ -41,7 +51,7 @@</span><br><span> static int _stem ## _handler(const struct aco_option *opt, struct ast_variable *var, void *obj) \</span><br><span> { \</span><br><span> struct ast_geoloc_ ## _object *_thisobject = obj; \</span><br><span style="color: hsl(0, 100%, 40%);">- int enumval = _stem ## _str_to_enum(var->value); \</span><br><span style="color: hsl(120, 100%, 40%);">+ int enumval = geoloc_ ## _stem ## _str_to_enum(var->value); \</span><br><span> if (enumval == -1) { \</span><br><span> return -1; \</span><br><span> } \</span><br><span>@@ -49,6 +59,17 @@</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%);">+#define GEOLOC_ENUM_TO_NAME(_stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+const char * geoloc_ ## _stem ## _to_name(int ix) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ARRAY_IN_BOUNDS(ix, _stem ## _names)) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ return "none"; \</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { \</span><br><span style="color: hsl(120, 100%, 40%);">+ return _stem ## _names[ix]; \</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> #define CONFIG_ENUM_TO_STR(_object, _stem) \</span><br><span> static int _stem ## _to_str(const void *obj, const intptr_t *args, char **buf) \</span><br><span> { \</span><br><span>@@ -63,6 +84,7 @@</span><br><span> </span><br><span> #define CONFIG_ENUM(_object, _stem) \</span><br><span> CONFIG_STR_TO_ENUM(_stem) \</span><br><span style="color: hsl(120, 100%, 40%);">+GEOLOC_ENUM_TO_NAME(_stem) \</span><br><span> CONFIG_ENUM_HANDLER(_object, _stem) \</span><br><span> CONFIG_ENUM_TO_STR(_object, _stem)</span><br><span> </span><br><span>@@ -133,6 +155,10 @@</span><br><span> int geoloc_channel_load(void);</span><br><span> int geoloc_channel_reload(void);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_eprofile_unload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_eprofile_load(void);</span><br><span style="color: hsl(120, 100%, 40%);">+int geoloc_eprofile_reload(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ast_sorcery *geoloc_get_sorcery(void);</span><br><span> </span><br><span> #endif /* GEOLOC_PRIVATE_H_ */</span><br><span>diff --git a/res/res_geolocation/pidf_lo_test.xml b/res/res_geolocation/pidf_lo_test.xml</span><br><span>new file mode 100644</span><br><span>index 0000000..3948063</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/pidf_lo_test.xml</span><br><span>@@ -0,0 +1,312 @@</span><br><span style="color: hsl(120, 100%, 40%);">+<?xml version="1.0" encoding="UTF-8"?></span><br><span style="color: hsl(120, 100%, 40%);">+<presence entity="pres:alice@asterisk.org"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns="urn:ietf:params:xml:ns:pidf"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:ca="urn:ietf:params:xml:ns:pidf:geopriv10:civicAddr"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:dm="urn:ietf:params:xml:ns:pidf:data-model"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gbp="urn:ietf:params:xml:ns:pidf:geopriv10:basicPolicy"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gml="http://www.opengis.net/gml"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gs="http://www.opengis.net/pidflo/1.0"></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="point-2d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Point srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>-34.410649 150.87651</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Point></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Manual</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:person id="point-3d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Point srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>-34.410649 150.87651 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Point></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>802.11</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:timestamp>2007-06-24T12:28:04Z</dm:timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </dm:person></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="circle-2d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:Circle srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>-34.410649 150.87651</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:radius uom="urn:ogc:def:uom:EPSG::9001">30</gs:radius></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:Circle></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>802.11</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="circle-3d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:Circle srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>-34.410649 150.87651 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:radius uom="urn:ogc:def:uom:EPSG::9001">30</gs:radius></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:Circle></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>802.11</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:person id="polygon-2d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.311 -73.422</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.111 -73.322</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.111 -73.222</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.311 -73.122</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.411 -73.222</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.411 -73.322</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.311 -73.422</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Polygon></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>802.11</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:timestamp>2007-06-24T12:28:04Z</dm:timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </dm:person></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:person id="polygon-3d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.311 -73.422 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.111 -73.322 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.111 -73.222 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.311 -73.122 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.411 -73.222 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.411 -73.322 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>43.311 -73.422 1800</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Polygon></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>802.11</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:timestamp>2007-06-24T12:28:04Z</dm:timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </dm:person></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="polygon-poslist-2d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:posList></span><br><span style="color: hsl(120, 100%, 40%);">+ 43.311 -73.422 43.111 -73.322</span><br><span style="color: hsl(120, 100%, 40%);">+ 43.111 -73.222 43.311 -73.122</span><br><span style="color: hsl(120, 100%, 40%);">+ 43.411 -73.222 43.411 -73.322</span><br><span style="color: hsl(120, 100%, 40%);">+ 43.311 -73.422</span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:posList></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Polygon></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Wiremap</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="polygon-poslist-3d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:posList></span><br><span style="color: hsl(120, 100%, 40%);">+ 43.311 -73.422 1800 43.111 -73.322 1800</span><br><span style="color: hsl(120, 100%, 40%);">+ 43.111 -73.222 1800 43.311 -73.122 1800</span><br><span style="color: hsl(120, 100%, 40%);">+ 43.411 -73.222 1800 43.411 -73.322 1800</span><br><span style="color: hsl(120, 100%, 40%);">+ 43.311 -73.422 1800</span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:posList></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Polygon></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Wiremap</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="ellipse-2d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:Ellipse srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>42.5463 -73.2512</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:semiMajorAxis uom="urn:ogc:def:uom:EPSG::9001">1275</gs:semiMajorAxis></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:semiMinorAxis uom="urn:ogc:def:uom:EPSG::9001">670</gs:semiMinorAxis></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:orientation uom="urn:ogc:def:uom:EPSG::9102">43.2</gs:orientation></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:Ellipse></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules/></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Device-Assisted_A-GPS</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:device id="arcband-2d"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:ArcBand srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>-43.5723 153.21760</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:innerRadius uom="urn:ogc:def:uom:EPSG::9001">3594</gs:innerRadius></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:outerRadius uom="urn:ogc:def:uom:EPSG::9001">4148</gs:outerRadius></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:startAngle uom="urn:ogc:def:uom:EPSG::9102">20</gs:startAngle></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:openingAngle uom="urn:ogc:def:uom:EPSG::9102">20</gs:openingAngle></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:ArcBand></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:retransmission-allowed>yes</gp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:ruleset-preference>https:/www/more.com</gp:ruleset-preference></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:retention-expires>2007-06-22T20:57:29Z</gp:retention-expires></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>TA-NMR</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:deviceID>mac:1234567890ab</dm:deviceID></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:timestamp>2007-06-22T20:57:29Z</dm:timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </dm:device></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="sphere"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:Sphere srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>42.5463 -73.2512 26.3</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:radius uom="urn:ogc:def:uom:EPSG::9001">850.24</gs:radius></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:Sphere></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Device-Based_A-GPS</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="ellipsoid"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:Ellipsoid srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:pos>42.5463 -73.2512 26.3</gml:pos></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:semiMajorAxis uom="urn:ogc:def:uom:EPSG::9001">7.7156</gs:semiMajorAxis></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:semiMinorAxis uom="urn:ogc:def:uom:EPSG::9001">3.31</gs:semiMinorAxis></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:verticalAxis uom="urn:ogc:def:uom:EPSG::9001">28.7</gs:verticalAxis></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:orientation uom="urn:ogc:def:uom:EPSG::9102">90</gs:orientation></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:Ellipsoid></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules/></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Hybrid_A-GPS</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <tuple id="prism"></span><br><span style="color: hsl(120, 100%, 40%);">+ <status></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:Prism srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:base></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:Polygon></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ <gml:posList></span><br><span style="color: hsl(120, 100%, 40%);">+ 42.556844 -73.248157 36.6 <!--A --></span><br><span style="color: hsl(120, 100%, 40%);">+ 42.656844 -73.248157 36.6 <!--B --></span><br><span style="color: hsl(120, 100%, 40%);">+ 42.656844 -73.348157 36.6 <!--C --></span><br><span style="color: hsl(120, 100%, 40%);">+ 42.556844 -73.348157 36.6 <!--D --></span><br><span style="color: hsl(120, 100%, 40%);">+ 42.556844 -73.248157 36.6 <!--A --></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:posList></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:LinearRing></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:exterior></span><br><span style="color: hsl(120, 100%, 40%);">+ </gml:Polygon></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:base></span><br><span style="color: hsl(120, 100%, 40%);">+ <gs:height uom="urn:ogc:def:uom:EPSG::9001">2.4</gs:height></span><br><span style="color: hsl(120, 100%, 40%);">+ </gs:Prism></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules/></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>Wiremap</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ </status></span><br><span style="color: hsl(120, 100%, 40%);">+ <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </tuple></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:device></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:civicAddress xml:lang="en-AU"></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:country>AU</ca:country></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:A1>NSW</ca:A1></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:A3>Wollongong</ca:A3></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:A4>North Wollongong</ca:A4></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:RD>Flinders</ca:RD></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:STS>Street</ca:STS></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:RDBR>Campbell Street</ca:RDBR></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:LMK>Gilligan's Island</ca:LMK></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:LOC>Corner</ca:LOC></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:NAM> Video Rental Store </ca:NAM></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:PC>2500</ca:PC></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:ROOM> Westerns and Classics </ca:ROOM></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:PLC>store</ca:PLC></span><br><span style="color: hsl(120, 100%, 40%);">+ <ca:POBOX>Private Box 15</ca:POBOX></span><br><span style="color: hsl(120, 100%, 40%);">+ </ca:civicAddress></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:location-info></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:retransmission-allowed>yes</gp:retransmission-allowed></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:ruleset-preference>https:/www/more.com</gp:ruleset-preference></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:retention-expires>2007-06-22T20:57:29Z</gp:retention-expires></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:usage-rules></span><br><span style="color: hsl(120, 100%, 40%);">+ <gp:method>GPS</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+ </gp:geopriv></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:deviceID>mac:1234567890ab</dm:deviceID></span><br><span style="color: hsl(120, 100%, 40%);">+ <dm:timestamp>2007-06-22T20:57:29Z</dm:timestamp></span><br><span style="color: hsl(120, 100%, 40%);">+ </dm:device></span><br><span style="color: hsl(120, 100%, 40%);">+</presence></span><br><span>diff --git a/res/res_geolocation/pidf_to_eprofile.xslt b/res/res_geolocation/pidf_to_eprofile.xslt</span><br><span>new file mode 100644</span><br><span>index 0000000..409ba9e</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_geolocation/pidf_to_eprofile.xslt</span><br><span>@@ -0,0 +1,124 @@</span><br><span style="color: hsl(120, 100%, 40%);">+<?xml version="1.0"?></span><br><span style="color: hsl(120, 100%, 40%);">+<xsl:stylesheet version="1.0"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:ca="urn:ietf:params:xml:ns:pidf:geopriv10:civicAddr"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:def="urn:ietf:params:xml:ns:pidf"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:dm="urn:ietf:params:xml:ns:pidf:data-model"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:fn="http://www.w3.org/2005/xpath-functions"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gbp="urn:ietf:params:xml:ns:pidf:geopriv10:basicPolicy"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gml="http://www.opengis.net/gml"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:gs="http://www.opengis.net/pidflo/1.0"</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"></span><br><span style="color: hsl(120, 100%, 40%);">+ <!--xsl:output method="text" /--></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:strip-space elements="*" /></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:param name="path"/></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template name="name-value"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:value-of select="local-name(.)" /><xsl:text>="</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:value-of select="normalize-space(.)" /><xsl:text>"</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:if test="following-sibling::*"><xsl:text>, </xsl:text></xsl:if></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template name="length"><xsl:call-template name="name-value" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template name="angle"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:value-of select="local-name(.)" /><xsl:text>="</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:value-of select="normalize-space(.)" /><xsl:text>"</xsl:text><xsl:text>, </xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:value-of select="local-name(.)" /><xsl:text>_uom="</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:when test="@uom = 'urn:ogc:def:uom:EPSG::9102'"><xsl:text>radians</xsl:text></xsl:when></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:otherwise><xsl:text>degrees</xsl:text></xsl:otherwise></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:text>"</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:if test="following-sibling::*"><xsl:text>, </xsl:text></xsl:if></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:orientation"><xsl:call-template name="angle" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:radius"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:height"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:semiMajorAxis"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:semiMinorAxis"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:verticalAxis"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:innerRadius"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:outerRadius"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:startAngle"><xsl:call-template name="angle" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gs:openingAngle"><xsl:call-template name="angle" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gml:pos"><xsl:call-template name="name-value" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gml:posList"><xsl:call-template name="name-value" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template name="shape"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:text>format="gml", type="</xsl:text><xsl:value-of select="local-name(.)" /><xsl:text>", </xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:text>crs="</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:when test="@srsName = 'urn:ogc:def:crs:EPSG::4326'"><xsl:text>2d</xsl:text></xsl:when></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:when test="@srsName = 'urn:ogc:def:crs:EPSG::4979'"><xsl:text>3d</xsl:text></xsl:when></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:otherwise><xsl:text>unknown</xsl:text></xsl:otherwise></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:text>", </xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="ca:civicAddress/*"><xsl:call-template name="name-value" /> </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template name="civicAddress"><xsl:text>format="civicAddress", </xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:location-info/gml:*"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="location-info"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:attribute name="format">gml</xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:call-template name="shape" /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:location-info/gs:*"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="location-info"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:attribute name="format">gml</xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:call-template name="shape" /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:location-info/ca:*"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="location-info"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:attribute name="format">civicAddress</xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:call-template name="civicAddress" /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:usage-rules/*"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:call-template name="name-value" /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:usage-rules"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="usage-rules"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:method"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:value-of select="normalize-space(.)" /></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template name="topnode"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="pidf-element"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:attribute name="name"><xsl:value-of select="local-name(.)"/></xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates select=".//gp:location-info"/></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates select=".//gp:usage-rules"/></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="method"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates select=".//gp:method"/></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+</xsl:text></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="dm:device"><xsl:call-template name="topnode" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="def:tuple"><xsl:call-template name="topnode" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="dm:person"><xsl:call-template name="topnode" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="/"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:element name="presence"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:attribute name="entity"><xsl:value-of select="/*/@entity"/></xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:apply-templates select="$path"/></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+ </xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+</xsl:stylesheet></span><br><span>diff --git a/tests/test_config.c b/tests/test_config.c</span><br><span>index 1a0ddaf..08c1bb1 100644</span><br><span>--- a/tests/test_config.c</span><br><span>+++ b/tests/test_config.c</span><br><span>@@ -1962,7 +1962,7 @@</span><br><span> }</span><br><span> </span><br><span> parse_string = "abc = 'def', ghi = 'j,kl', mno='pq=r', stu = 'vwx=\"yz\", ABC = \"DEF\"'";</span><br><span style="color: hsl(0, 100%, 40%);">- list = ast_variable_list_from_string(parse_string, ",", "=");</span><br><span style="color: hsl(120, 100%, 40%);">+ list = ast_variable_list_from_string(parse_string, ",", "=", "'");</span><br><span> ast_test_validate(test, list != NULL);</span><br><span> str = ast_variable_list_join(list, "|", "^", "@", NULL);</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/+/18127">change 18127</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/+/18127"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: development/16/geolocation </div>
<div style="display:none"> Gerrit-Change-Id: I50b66bd041b2a62ab329406f20dbaeef1fa68fc1 </div>
<div style="display:none"> Gerrit-Change-Number: 18127 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>