<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18953">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_geolocation: Address user issues, remove complexity, plug leaks<br><br>* Added processing for the 'confidence' element.<br>* Added documentation to some APIs.<br>* removed a lot of complex code related to the very-off-nominal<br>  case of needing to process multiple location info sources.<br>* Create a new 'ast_geoloc_eprofile_to_pidf' API that just takes<br>  one eprofile instead of a datastore of multiples.<br>* Plugged a huge leak in XML processing that arose from<br>  insufficient documentation by the libxml/libxslt authors.<br>* Refactored stylesheets to be more efficient.<br>* Renamed 'profile_action' to 'profile_precedence' to better<br>  reflect it's purpose.<br>* Added the config option for 'allow_routing_use' which<br>  sets the value of the 'Geolocation-Routing' header.<br>* Removed the GeolocProfileCreate and GeolocProfileDelete<br>  dialplan apps.<br>* Changed the GEOLOC_PROFILE dialplan function as follows:<br>  * Removed the 'profile' argument.<br>  * Automatically create a profile if it doesn't exist.<br>  * Delete a profile if 'inheritable' is set to no.<br>* Fixed various bugs and leaks<br>* Updated Asterisk WiKi documentation.<br><br>ASTERISK-30167<br><br>Change-Id: If38c23f26228e96165be161c2f5e849cb8e16fa0<br>(cherry picked from commit dfedb13ecab3f9b8c614351b85fe77cf0ec6baa2)<br>---<br>M configs/samples/geolocation.conf.sample<br>A doc/CHANGES-staging/res_geolocation.txt<br>M include/asterisk/res_geolocation.h<br>M include/asterisk/xml.h<br>M main/xml.c<br>M res/res_geolocation/eprofile_to_pidf.xslt<br>M res/res_geolocation/geoloc_config.c<br>M res/res_geolocation/geoloc_dialplan.c<br>M res/res_geolocation/geoloc_doc.xml<br>M res/res_geolocation/geoloc_eprofile.c<br>M res/res_geolocation/geoloc_gml.c<br>M res/res_geolocation/geoloc_private.h<br>M res/res_geolocation/pidf_lo_test.xml<br>M res/res_geolocation/pidf_to_eprofile.xslt<br>M res/res_geolocation/wiki/AsteriskImplementation.md<br>M res/res_pjsip_geolocation.c<br>16 files changed, 1,119 insertions(+), 1,258 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/53/18953/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configs/samples/geolocation.conf.sample b/configs/samples/geolocation.conf.sample</span><br><span>index 0566cbd..8c44edb 100644</span><br><span>--- a/configs/samples/geolocation.conf.sample</span><br><span>+++ b/configs/samples/geolocation.conf.sample</span><br><span>@@ -134,14 +134,24 @@</span><br><span> Example:</span><br><span> location_source = sip1.myserver.net</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+-- confidence (optional) -----------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+The confidence in the location specified.</span><br><span style="color: hsl(120, 100%, 40%);">+confidence = pdf=[ unknown | normal | rectangular ], value=<percent_confident></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Please see RFC7459 for the exact description of this parameter.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Example:</span><br><span style="color: hsl(120, 100%, 40%);">+confidence = pdf=normal, value=75</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> -- Location Example ---------------------------------------------------</span><br><span> </span><br><span> [mylocation]</span><br><span> type = location</span><br><span> format = civicAddress</span><br><span> location_info = country=US</span><br><span style="color: hsl(0, 100%, 40%);">-location_info = A1="New York", A3="New York", A4=Manhattan  </span><br><span style="color: hsl(0, 100%, 40%);">-location_info = HNO=1633, PRD=W, RD=46th, STS=Street  </span><br><span style="color: hsl(120, 100%, 40%);">+location_info = A1="New York", A3="New York", A4=Manhattan</span><br><span style="color: hsl(120, 100%, 40%);">+location_info = HNO=1633, PRD=W, RD=46th, STS=Street</span><br><span> location_info = PC=10222</span><br><span> method = Manual</span><br><span> location_source = sip1.myserver.net</span><br><span>@@ -160,9 +170,9 @@</span><br><span> Defines the object type.</span><br><span> type = profile</span><br><span> </span><br><span>--- profile_action (optional) ------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+-- profile_precedence (optional) ------------------------------------------</span><br><span> Sets how to reconcile incoming and configured profiles.</span><br><span style="color: hsl(0, 100%, 40%);">-profile_action = < prefer_incoming | prefer_config | discard_incoming</span><br><span style="color: hsl(120, 100%, 40%);">+profile_precedence = < prefer_incoming | prefer_config | discard_incoming</span><br><span>     | discard_config ></span><br><span> </span><br><span> On an incoming call leg, "incoming" is the location description</span><br><span>@@ -188,7 +198,7 @@</span><br><span> discard_incoming is the default.</span><br><span> </span><br><span> Example:</span><br><span style="color: hsl(0, 100%, 40%);">-profile_action = prefer_config</span><br><span style="color: hsl(120, 100%, 40%);">+profile_precedence = prefer_config</span><br><span> </span><br><span> -- pidf_element (optional) --------------------------------------------</span><br><span> PIDF-LO element in which to place the location description.</span><br><span>@@ -207,10 +217,10 @@</span><br><span> Example:</span><br><span> pidf_element = tuple</span><br><span> </span><br><span>--- geolocation_routing (optional) -------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+-- allow_routing_use (optional) -------------------------------------</span><br><span> Sets whether the "Geolocation-Routing" header is added to outgoing</span><br><span> requests.</span><br><span style="color: hsl(0, 100%, 40%);">-geolocation_routing = < yes | no ></span><br><span style="color: hsl(120, 100%, 40%);">+allow_routing_use = < yes | no ></span><br><span> </span><br><span> Set to "yes" to indicate that servers later in the path</span><br><span> can use the location information for routing purposes.  Set to "no"</span><br><span>@@ -218,7 +228,7 @@</span><br><span> "Geolocation-Routing" header will be added.</span><br><span> </span><br><span> Example:</span><br><span style="color: hsl(0, 100%, 40%);">-geolocation_routing = yes</span><br><span style="color: hsl(120, 100%, 40%);">+allow_routing_use = yes</span><br><span> </span><br><span> -- location_reference (optional) --------------------------------------</span><br><span> The name of an existing Location object.</span><br><span>diff --git a/doc/CHANGES-staging/res_geolocation.txt b/doc/CHANGES-staging/res_geolocation.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..a93d7b6</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/res_geolocation.txt</span><br><span>@@ -0,0 +1,23 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_geolocation</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+* Added processing for the 'confidence' element.</span><br><span style="color: hsl(120, 100%, 40%);">+* Added documentation to some APIs.</span><br><span style="color: hsl(120, 100%, 40%);">+* removed a lot of complex code related to the very-off-nominal</span><br><span style="color: hsl(120, 100%, 40%);">+  case of needing to process multiple location info sources.</span><br><span style="color: hsl(120, 100%, 40%);">+* Create a new 'ast_geoloc_eprofile_to_pidf' API that just takes</span><br><span style="color: hsl(120, 100%, 40%);">+  one eprofile instead of a datastore of multiples.</span><br><span style="color: hsl(120, 100%, 40%);">+* Plugged a huge leak in XML processing that arose from</span><br><span style="color: hsl(120, 100%, 40%);">+  insufficient documentation by the libxml/libxslt authors.</span><br><span style="color: hsl(120, 100%, 40%);">+* Refactored stylesheets to be more efficient.</span><br><span style="color: hsl(120, 100%, 40%);">+* Renamed 'profile_action' to 'profile_precedence' to better</span><br><span style="color: hsl(120, 100%, 40%);">+  reflect it's purpose.</span><br><span style="color: hsl(120, 100%, 40%);">+* Added the config option for 'allow_routing_use' which</span><br><span style="color: hsl(120, 100%, 40%);">+  sets the value of the 'Geolocation-Routing' header.</span><br><span style="color: hsl(120, 100%, 40%);">+* Removed the GeolocProfileCreate and GeolocProfileDelete</span><br><span style="color: hsl(120, 100%, 40%);">+  dialplan apps.</span><br><span style="color: hsl(120, 100%, 40%);">+* Changed the GEOLOC_PROFILE dialplan function as follows:</span><br><span style="color: hsl(120, 100%, 40%);">+  * Removed the 'profile' argument.</span><br><span style="color: hsl(120, 100%, 40%);">+  * Automatically create a profile if it doesn't exist.</span><br><span style="color: hsl(120, 100%, 40%);">+  * Delete a profile if 'inheritable' is set to no.</span><br><span style="color: hsl(120, 100%, 40%);">+* Fixed various bugs and leaks</span><br><span style="color: hsl(120, 100%, 40%);">+* Updated Asterisk WiKi documentation.</span><br><span>diff --git a/include/asterisk/res_geolocation.h b/include/asterisk/res_geolocation.h</span><br><span>index 403e6c8..31426c0c 100644</span><br><span>--- a/include/asterisk/res_geolocation.h</span><br><span>+++ b/include/asterisk/res_geolocation.h</span><br><span>@@ -29,8 +29,8 @@</span><br><span> </span><br><span> enum ast_geoloc_pidf_element {</span><br><span>       AST_PIDF_ELEMENT_NONE = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-      AST_PIDF_ELEMENT_TUPLE,</span><br><span>      AST_PIDF_ELEMENT_DEVICE,</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_PIDF_ELEMENT_TUPLE,</span><br><span>      AST_PIDF_ELEMENT_PERSON,</span><br><span>     AST_PIDF_ELEMENT_LAST,</span><br><span> };</span><br><span>@@ -43,13 +43,22 @@</span><br><span>   AST_GEOLOC_FORMAT_LAST,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-enum ast_geoloc_action {</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_GEOLOC_ACT_PREFER_INCOMING = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-     AST_GEOLOC_ACT_PREFER_CONFIG,</span><br><span style="color: hsl(0, 100%, 40%);">-   AST_GEOLOC_ACT_DISCARD_INCOMING,</span><br><span style="color: hsl(0, 100%, 40%);">-        AST_GEOLOC_ACT_DISCARD_CONFIG,</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_geoloc_precedence {</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_GEOLOC_PRECED_PREFER_INCOMING = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_GEOLOC_PRECED_PREFER_CONFIG,</span><br><span style="color: hsl(120, 100%, 40%);">+      AST_GEOLOC_PRECED_DISCARD_INCOMING,</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_GEOLOC_PRECED_DISCARD_CONFIG,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define CONFIG_STR_TO_ENUM_DECL(_stem) int ast_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(precedence);</span><br><span style="color: hsl(120, 100%, 40%);">+#define GEOLOC_ENUM_TO_NAME_DECL(_stem) const char * ast_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(precedence);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct ast_geoloc_location {</span><br><span>    SORCERY_OBJECT(details);</span><br><span>     AST_DECLARE_STRING_FIELDS(</span><br><span>@@ -58,6 +67,7 @@</span><br><span>       );</span><br><span>   enum ast_geoloc_format format;</span><br><span>       struct ast_variable *location_info;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_variable *confidence;</span><br><span> };</span><br><span> </span><br><span> struct ast_geoloc_profile {</span><br><span>@@ -67,8 +77,8 @@</span><br><span>                AST_STRING_FIELD(notes);</span><br><span>     );</span><br><span>   enum ast_geoloc_pidf_element pidf_element;</span><br><span style="color: hsl(0, 100%, 40%);">-      enum ast_geoloc_action action;</span><br><span style="color: hsl(0, 100%, 40%);">-  int geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+      enum ast_geoloc_precedence precedence;</span><br><span style="color: hsl(120, 100%, 40%);">+        int allow_routing_use;</span><br><span>       struct ast_variable *location_refinement;</span><br><span>    struct ast_variable *location_variables;</span><br><span>     struct ast_variable *usage_rules;</span><br><span>@@ -83,14 +93,15 @@</span><br><span>              AST_STRING_FIELD(notes);</span><br><span>     );</span><br><span>   enum ast_geoloc_pidf_element pidf_element;</span><br><span style="color: hsl(0, 100%, 40%);">-      enum ast_geoloc_action action;</span><br><span style="color: hsl(0, 100%, 40%);">-  int geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+      enum ast_geoloc_precedence precedence;</span><br><span style="color: hsl(120, 100%, 40%);">+        int allow_routing_use;</span><br><span>       enum ast_geoloc_format format;</span><br><span>       struct ast_variable *location_info;</span><br><span>  struct ast_variable *location_refinement;</span><br><span>    struct ast_variable *location_variables;</span><br><span>     struct ast_variable *effective_location;</span><br><span>     struct ast_variable *usage_rules;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_variable *confidence;</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span>@@ -331,13 +342,46 @@</span><br><span> struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_uri(const char *uri,</span><br><span>        const char *reference_string);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Convert a URI eprofile to a URI string</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param eprofile   Effective profile to convert</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan       Channel to use to resolve variables</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buf        Pointer to ast_str pointer to use for work</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ref_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 String representation of URI allocated from buf or NULL on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> const char *ast_geoloc_eprofile_to_uri(struct ast_geoloc_eprofile *eprofile,</span><br><span>    struct ast_channel *chan, struct ast_str **buf, const char *ref_string);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Convert a datastore containing eprofiles to a PIDF-LO document</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ds         Datastore containing effective profiles to convert</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan       Channel to use to resolve variables</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buf        Pointer to ast_str pointer to use for work</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ref_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 String representation PIDF-LO allocated from buf or NULL on failure.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> const char *ast_geoloc_eprofiles_to_pidf(struct ast_datastore *ds,</span><br><span>    struct ast_channel *chan, struct ast_str **buf, const char * ref_string);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Convert a single eprofile to a PIDF-LO document</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param eprofile   Effective profile to convert</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan       Channel to use to resolve variables</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buf        Pointer to ast_str pointer to use for work</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param ref_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 String representation PIDF-LO allocated from buf or NULL on failure.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *ast_geoloc_eprofile_to_pidf(struct ast_geoloc_eprofile *eprofile,</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_channel *chan, struct ast_str **buf, const char * ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \brief Refresh the effective profile with any changed info.</span><br><span>  *</span><br><span>  * \param eprofile The eprofile to refresh.</span><br><span>diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h</span><br><span>index c1b0797..5c2e9f9 100644</span><br><span>--- a/include/asterisk/xml.h</span><br><span>+++ b/include/asterisk/xml.h</span><br><span>@@ -163,6 +163,7 @@</span><br><span>  * \param attrname Attribute name.</span><br><span>  * \retval NULL on error</span><br><span>  * \return The attribute value on success.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note The result must be freed with ast_xml_free_attr().</span><br><span>  */</span><br><span> const char *ast_xml_get_attribute(struct ast_xml_node *node, const char *attrname);</span><br><span> </span><br><span>diff --git a/main/xml.c b/main/xml.c</span><br><span>index d244e4e..8c49a9e 100644</span><br><span>--- a/main/xml.c</span><br><span>+++ b/main/xml.c</span><br><span>@@ -544,35 +544,45 @@</span><br><span> {</span><br><span>  xsltStylesheet *xslt = (xsltStylesheet *)axslt;</span><br><span>      xmlDoc *xml = (xmlDoc *)axml;</span><br><span style="color: hsl(120, 100%, 40%);">+ xmlDoc *res;</span><br><span>         xsltTransformContextPtr ctxt;</span><br><span>        xmlNs *ns;</span><br><span style="color: hsl(0, 100%, 40%);">-      xmlDoc *res;</span><br><span>         int options = XSLT_PARSE_OPTIONS;</span><br><span> </span><br><span>        /*</span><br><span>    * Normally we could just call xsltApplyStylesheet() without creating</span><br><span style="color: hsl(0, 100%, 40%);">-    * our own transform context but we need to pass parameters to it</span><br><span style="color: hsl(0, 100%, 40%);">-        * that have namespace prefixes and that's not supported.  Instead</span><br><span style="color: hsl(0, 100%, 40%);">-   * we have to create a transform context, iterate over the namespace</span><br><span style="color: hsl(0, 100%, 40%);">-     * declarations in the stylesheet (not the incoming xml document),</span><br><span style="color: hsl(0, 100%, 40%);">-       * and add them to the transform context's xpath context.</span><br><span style="color: hsl(120, 100%, 40%);">+  * our own transform context but passing parameters to it that have</span><br><span style="color: hsl(120, 100%, 40%);">+    * namespace prefixes isn't supported. Instead we have to create a</span><br><span style="color: hsl(120, 100%, 40%);">+         * transform context, iterate over the namespace declarations in the</span><br><span style="color: hsl(120, 100%, 40%);">+   * stylesheet (not the incoming xml document), add them to the</span><br><span style="color: hsl(120, 100%, 40%);">+         * transform context's xpath context, and call xsltApplyStylesheetUser.</span><br><span>   *</span><br><span style="color: hsl(0, 100%, 40%);">-       * The alternative would be to pass the parameters with namespaces</span><br><span style="color: hsl(0, 100%, 40%);">-       * as text strings but that's not intuitive and results in much</span><br><span style="color: hsl(0, 100%, 40%);">-      * slower performance than adding the namespaces here.</span><br><span style="color: hsl(120, 100%, 40%);">+         * Since this is a bit involved and libxslt apparently doesn't completely</span><br><span style="color: hsl(120, 100%, 40%);">+  * clean up after itself in this situation,  we'll only do that dance</span><br><span style="color: hsl(120, 100%, 40%);">+      * if there are parameters passed in.  Otherwise we just call the simpler</span><br><span style="color: hsl(120, 100%, 40%);">+      * xsltApplyStylesheet.</span><br><span style="color: hsl(120, 100%, 40%);">+        *</span><br><span>    */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!params) {</span><br><span style="color: hsl(120, 100%, 40%);">+                res = xsltApplyStylesheet(xslt, xml, params);</span><br><span style="color: hsl(120, 100%, 40%);">+         return (struct ast_xml_doc *)res;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  ctxt = xsltNewTransformContext(xslt, xml);</span><br><span>   xsltSetCtxtParseOptions(ctxt, options);</span><br><span> </span><br><span>  for (ns = xslt->doc->children->nsDef; ns; ns = ns->next) {</span><br><span>               if (xmlXPathRegisterNs(ctxt->xpathCtxt, ns->prefix, ns->href) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  xmlXPathFreeContext(ctxt->xpathCtxt);</span><br><span>                     xsltFreeTransformContext(ctxt);</span><br><span>                      return NULL;</span><br><span>                 }</span><br><span>    }</span><br><span> </span><br><span>        res = xsltApplyStylesheetUser(xslt, xml, params, NULL, NULL, ctxt);</span><br><span style="color: hsl(120, 100%, 40%);">+   xmlXPathFreeContext(ctxt->xpathCtxt);</span><br><span style="color: hsl(120, 100%, 40%);">+      ctxt->xpathCtxt = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    xsltFreeTransformContext(ctxt);</span><br><span> </span><br><span>  return (struct ast_xml_doc *)res;</span><br><span> }</span><br><span>diff --git a/res/res_geolocation/eprofile_to_pidf.xslt b/res/res_geolocation/eprofile_to_pidf.xslt</span><br><span>index dbfe17b..dec73ed 100644</span><br><span>--- a/res/res_geolocation/eprofile_to_pidf.xslt</span><br><span>+++ b/res/res_geolocation/eprofile_to_pidf.xslt</span><br><span>@@ -8,6 +8,7 @@</span><br><span>    xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"</span><br><span>   xmlns:gs="http://www.opengis.net/pidflo/1.0"</span><br><span>       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</span><br><span style="color: hsl(120, 100%, 40%);">+    xmlns:con="urn:ietf:params:xml:ns:geopriv:conf"</span><br><span>    xmlns:date="http://exslt.org/dates-and-times"></span><br><span> </span><br><span>      <xsl:output method="xml" indent="yes"/></span><br><span>@@ -20,12 +21,16 @@</span><br><span>              <!-- xslt will take care of adding all of the namespace declarations</span><br><span>                      from the list above --></span><br><span>           <presence xmlns="urn:ietf:params:xml:ns:pidf" entity="{@entity}"></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select="./device|tuple|person"/></span><br><span style="color: hsl(120, 100%, 40%);">+                 <xsl:apply-templates/></span><br><span>                 </presence></span><br><span>    </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="device"></span><br><span style="color: hsl(0, 100%, 40%);">-           <dm:device></span><br><span style="color: hsl(120, 100%, 40%);">+     <xsl:template match="person|device"></span><br><span style="color: hsl(120, 100%, 40%);">+          <xsl:element name="dm:{local-name(.)}"></span><br><span style="color: hsl(120, 100%, 40%);">+                       <xsl:if test="@id"></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:if></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                    <gp:geopriv></span><br><span>                           <xsl:apply-templates select="./location-info"/></span><br><span>                              <xsl:apply-templates select="./usage-rules"/></span><br><span>@@ -42,7 +47,7 @@</span><br><span>                                    <xsl:value-of select="./deviceID"/></span><br><span>                          </dm:deviceID></span><br><span>                         </xsl:if></span><br><span style="color: hsl(0, 100%, 40%);">-         </dm:device></span><br><span style="color: hsl(120, 100%, 40%);">+            </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span>    <xsl:template match="tuple"></span><br><span>@@ -63,21 +68,6 @@</span><br><span>            </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="person"></span><br><span style="color: hsl(0, 100%, 40%);">-           <dm:person></span><br><span style="color: hsl(0, 100%, 40%);">-                       <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <xsl:apply-templates select="./location-info"/></span><br><span style="color: hsl(0, 100%, 40%);">-                         <xsl:apply-templates select="./usage-rules"/></span><br><span style="color: hsl(0, 100%, 40%);">-                           <xsl:apply-templates select="./method"/></span><br><span style="color: hsl(0, 100%, 40%);">-                                <xsl:apply-templates select="./note-well"/></span><br><span style="color: hsl(0, 100%, 40%);">-                     </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:if test="./timestamp"></span><br><span style="color: hsl(0, 100%, 40%);">-                             <dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                                    <xsl:value-of select="./timestamp"/></span><br><span style="color: hsl(0, 100%, 40%);">-                            </dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                   </xsl:if></span><br><span style="color: hsl(0, 100%, 40%);">-         </dm:person></span><br><span style="color: hsl(0, 100%, 40%);">-      </xsl:template></span><br><span> </span><br><span>    <xsl:template match="location-info"></span><br><span>                 <gp:location-info></span><br><span>@@ -233,5 +223,10 @@</span><br><span>      <xsl:template match="pos"><xsl:call-template name="name-value" /></xsl:template></span><br><span>       <xsl:template match="posList"><xsl:call-template name="name-value" /></xsl:template></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        <xsl:template match="confidence"></span><br><span style="color: hsl(120, 100%, 40%);">+             <con:confidence pdf="{@pdf}"></span><br><span style="color: hsl(120, 100%, 40%);">+                 <xsl:value-of select="."/></span><br><span style="color: hsl(120, 100%, 40%);">+            </con:confidence></span><br><span style="color: hsl(120, 100%, 40%);">+       </xsl:template></span><br><span> </span><br><span> </xsl:stylesheet></span><br><span>diff --git a/res/res_geolocation/geoloc_config.c b/res/res_geolocation/geoloc_config.c</span><br><span>index 33cd333..772bdc7 100644</span><br><span>--- a/res/res_geolocation/geoloc_config.c</span><br><span>+++ b/res/res_geolocation/geoloc_config.c</span><br><span>@@ -26,8 +26,8 @@</span><br><span> </span><br><span> static const char *pidf_element_names[] = {</span><br><span>         "<none>",</span><br><span style="color: hsl(0, 100%, 40%);">-       "tuple",</span><br><span>   "device",</span><br><span style="color: hsl(120, 100%, 40%);">+   "tuple",</span><br><span>   "person"</span><br><span> };</span><br><span> </span><br><span>@@ -38,7 +38,7 @@</span><br><span>     "URI",</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const char * action_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const char * precedence_names[] = {</span><br><span>         "prefer_incoming",</span><br><span>         "prefer_config",</span><br><span>   "discard_incoming",</span><br><span>@@ -47,12 +47,14 @@</span><br><span> </span><br><span> CONFIG_ENUM(location, format)</span><br><span> CONFIG_VAR_LIST(location, location_info)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_VAR_LIST(location, confidence)</span><br><span> </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>      ast_string_field_free_memory(location);</span><br><span>      ast_variables_destroy(location->location_info);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_variables_destroy(location->confidence);</span><br><span> }</span><br><span> </span><br><span> static void *geoloc_location_alloc(const char *name)</span><br><span>@@ -67,7 +69,7 @@</span><br><span> </span><br><span> </span><br><span> CONFIG_ENUM(profile, pidf_element)</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_ENUM(profile, action)</span><br><span style="color: hsl(120, 100%, 40%);">+CONFIG_ENUM(profile, precedence)</span><br><span> CONFIG_VAR_LIST(profile, location_refinement)</span><br><span> CONFIG_VAR_LIST(profile, location_variables)</span><br><span> CONFIG_VAR_LIST(profile, usage_rules)</span><br><span>@@ -308,7 +310,7 @@</span><br><span>     int using_regex = 0;</span><br><span>         char *result = CLI_SUCCESS;</span><br><span>  int ret = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    char *action;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *precedence;</span><br><span>    int count = 0;</span><br><span> </span><br><span>   switch (cmd) {</span><br><span>@@ -365,13 +367,13 @@</span><br><span>       for (; (profile = ao2_iterator_next(&iter)); ao2_ref(profile, -1)) {</span><br><span>             ao2_lock(profile);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          action_to_str(profile, NULL, &action);</span><br><span style="color: hsl(120, 100%, 40%);">+            precedence_to_str(profile, NULL, &precedence);</span><br><span>           ast_cli(a->fd, "%-46.46s %-16s %-s\n",</span><br><span>                  ast_sorcery_object_get_id(profile),</span><br><span style="color: hsl(0, 100%, 40%);">-                     action,</span><br><span style="color: hsl(120, 100%, 40%);">+                       precedence,</span><br><span>                  profile->location_reference);</span><br><span>             ao2_unlock(profile);</span><br><span style="color: hsl(0, 100%, 40%);">-            ast_free(action);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_free(precedence);</span><br><span>                count++;</span><br><span>     }</span><br><span>    ao2_iterator_destroy(&iter);</span><br><span>@@ -460,11 +462,11 @@</span><br><span>             variables_str = ast_variable_list_join(eprofile->location_variables, ",", "=", "\"", NULL);</span><br><span>            usage_rules_str = ast_variable_list_join(eprofile->usage_rules, ",", "=", "\"", NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                action_to_str(eprofile, NULL, &action);</span><br><span style="color: hsl(120, 100%, 40%);">+           precedence_to_str(eprofile, NULL, &action);</span><br><span> </span><br><span>          ast_cli(a->fd,</span><br><span>                    "id:                   %-s\n"</span><br><span style="color: hsl(0, 100%, 40%);">-                 "profile_action:       %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "profile_disposition:  %-s\n"</span><br><span>                      "pidf_element:         %-s\n"</span><br><span>                      "location_reference:   %-s\n"</span><br><span>                      "Location_format:      %-s\n"</span><br><span>@@ -472,6 +474,7 @@</span><br><span>                        "location_method:      %-s\n"</span><br><span>                      "location_refinement:  %-s\n"</span><br><span>                      "location_variables:   %-s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                       "allow_routing_use:    %-s\n"</span><br><span>                      "effective_location:   %-s\n"</span><br><span>                      "usage_rules:          %-s\n"</span><br><span>                      "notes:                %-s\n",</span><br><span>@@ -484,6 +487,7 @@</span><br><span>                       S_OR(eprofile->method, "<none>"),</span><br><span>                         S_COR(refinement_str, ast_str_buffer(refinement_str), "<none>"),</span><br><span>                     S_COR(variables_str, ast_str_buffer(variables_str), "<none>"),</span><br><span style="color: hsl(120, 100%, 40%);">+                        S_COR(eprofile->precedence, "yes", "no"),</span><br><span>                     S_COR(resolved_str, ast_str_buffer(resolved_str), "<none>"),</span><br><span>                         S_COR(usage_rules_str, ast_str_buffer(usage_rules_str), "<none>"),</span><br><span>                   S_OR(eprofile->notes, "<none>")</span><br><span>@@ -597,6 +601,8 @@</span><br><span>             format_handler, format_to_str, NULL, 0, 0);</span><br><span>  ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "location_info", NULL,</span><br><span>              location_info_handler, location_info_to_str, location_info_dup, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_sorcery_object_field_register_custom(geoloc_sorcery, "location", "confidence", NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+          confidence_handler, confidence_to_str, confidence_dup, 0, 0);</span><br><span>        ast_sorcery_object_field_register(geoloc_sorcery, "location", "location_source", "", OPT_STRINGFIELD_T,</span><br><span>                0, STRFLDSET(struct ast_geoloc_location, location_source));</span><br><span>  ast_sorcery_object_field_register(geoloc_sorcery, "location", "method", "", OPT_STRINGFIELD_T,</span><br><span>@@ -616,8 +622,8 @@</span><br><span>           pidf_element_names[AST_PIDF_ELEMENT_DEVICE], 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 style="color: hsl(0, 100%, 40%);">-   ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "profile_action", "discard_incoming",</span><br><span style="color: hsl(0, 100%, 40%);">-         action_handler, action_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "profile_precedence", "discard_incoming",</span><br><span style="color: hsl(120, 100%, 40%);">+           precedence_handler, precedence_to_str, NULL, 0, 0);</span><br><span>  ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "usage_rules", NULL,</span><br><span>                 usage_rules_handler, usage_rules_to_str, usage_rules_dup, 0, 0);</span><br><span>     ast_sorcery_object_field_register_custom(geoloc_sorcery, "profile", "location_info_refinement", NULL,</span><br><span>@@ -626,6 +632,9 @@</span><br><span>              location_variables_handler, location_variables_to_str, location_variables_dup, 0, 0);</span><br><span>        ast_sorcery_object_field_register(geoloc_sorcery, "profile", "notes", "", OPT_STRINGFIELD_T,</span><br><span>           0, STRFLDSET(struct ast_geoloc_profile, notes));</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_sorcery_object_field_register(geoloc_sorcery, "profile", "allow_routing_use",</span><br><span style="color: hsl(120, 100%, 40%);">+         "no", OPT_BOOL_T, 1, FLDSET(struct ast_geoloc_profile, allow_routing_use));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span>  ast_sorcery_load(geoloc_sorcery);</span><br><span> </span><br><span>diff --git a/res/res_geolocation/geoloc_dialplan.c b/res/res_geolocation/geoloc_dialplan.c</span><br><span>index efa234a..c75189f 100644</span><br><span>--- a/res/res_geolocation/geoloc_dialplan.c</span><br><span>+++ b/res/res_geolocation/geoloc_dialplan.c</span><br><span>@@ -41,84 +41,63 @@</span><br><span>         const char *cmd, char *data, struct ast_str **buf, ssize_t len)</span><br><span> {</span><br><span>         char *parsed_data = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-  int index = -1;</span><br><span>      struct ast_datastore *ds;</span><br><span>    struct ast_geoloc_eprofile *eprofile = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    int profile_count = 0;</span><br><span> </span><br><span>   AST_DECLARE_APP_ARGS(args,</span><br><span>           AST_APP_ARG(field);</span><br><span style="color: hsl(0, 100%, 40%);">-             AST_APP_ARG(index);</span><br><span>  );</span><br><span> </span><br><span>       /* Check for zero arguments */</span><br><span>       if (ast_strlen_zero(parsed_data)) {</span><br><span>          ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span> </span><br><span>        AST_STANDARD_APP_ARGS(args, parsed_data);</span><br><span> </span><br><span>        if (ast_strlen_zero(args.field)) {</span><br><span>           ast_log(LOG_ERROR, "%s: Cannot call without a field to query\n", cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-                return -1;</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%);">-       if (!ast_strlen_zero(args.index)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (sscanf(args.index, "%30d", &index) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_log(LOG_ERROR, "%s: profile_index '%s' is invalid\n", cmd, args.index);</span><br><span style="color: hsl(0, 100%, 40%);">-                   return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(120, 100%, 40%);">+             pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span> </span><br><span>        ds = ast_geoloc_datastore_find(chan);</span><br><span>        if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_log(LOG_NOTICE, "%s: There are no geoloc profiles on this channel\n", cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-               return -1;</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%);">-       profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (index < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (ast_strings_equal(args.field, "count")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 ast_str_append(buf, len, "%d", profile_count);</span><br><span style="color: hsl(0, 100%, 40%);">-                } else if (ast_strings_equal(args.field, "inheritable")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_str_append(buf, len, "%d", ds->inheritance ? 1 : 0);</span><br><span style="color: hsl(0, 100%, 40%);">-           } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field);</span><br><span style="color: hsl(0, 100%, 40%);">-                 return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+               pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");</span><br><span>            return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (index >= profile_count) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "%s: index %d is out of range 0 -> %d\n", cmd, index, profile_count);</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1;</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%);">-       eprofile = ast_geoloc_datastore_get_eprofile(ds, index);</span><br><span style="color: hsl(120, 100%, 40%);">+      eprofile = ast_geoloc_datastore_get_eprofile(ds, 0);</span><br><span>         if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "%s: Internal Error.  Profile at index %d couldn't be retrieved.\n", cmd, index);</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_NOTICE, "%s: There is no geoloc profile on this channel\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+               pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_strings_equal(args.field, "id")) {</span><br><span style="color: hsl(120, 100%, 40%);">+  pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0");</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ast_strings_equal(args.field, "inheritable")) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_str_append(buf, len, "%s", ds->inheritance ? "true" : "false");</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (ast_strings_equal(args.field, "id")) {</span><br><span>          ast_str_append(buf, len, "%s", eprofile->id);</span><br><span>   } else if (ast_strings_equal(args.field, "location_reference")) {</span><br><span>          ast_str_append(buf, len, "%s", eprofile->location_reference);</span><br><span>   } else if (ast_strings_equal(args.field, "method")) {</span><br><span>              ast_str_append(buf, len, "%s", eprofile->method);</span><br><span style="color: hsl(0, 100%, 40%);">-  } else if (ast_strings_equal(args.field, "geolocation_routing")) {</span><br><span style="color: hsl(0, 100%, 40%);">-            ast_str_append(buf, len, "%s", eprofile->geolocation_routing ? "yes" : "no");</span><br><span style="color: hsl(0, 100%, 40%);">-  } else if (ast_strings_equal(args.field, "profile_action")) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_str_append(buf, len, "%s", geoloc_action_to_name(eprofile->action));</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ast_strings_equal(args.field, "allow_routing_use")) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_str_append(buf, len, "%s", eprofile->allow_routing_use ? "yes" : "no");</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (ast_strings_equal(args.field, "profile_precedence")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_str_append(buf, len, "%s", ast_geoloc_precedence_to_name(eprofile->precedence));</span><br><span>    } else if (ast_strings_equal(args.field, "format")) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_str_append(buf, len, "%s", geoloc_format_to_name(eprofile->format));</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_str_append(buf, len, "%s", ast_geoloc_format_to_name(eprofile->format));</span><br><span>    } else if (ast_strings_equal(args.field, "pidf_element")) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_str_append(buf, len, "%s", geoloc_pidf_element_to_name(eprofile->pidf_element));</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_str_append(buf, len, "%s", ast_geoloc_pidf_element_to_name(eprofile->pidf_element));</span><br><span>        } else if (ast_strings_equal(args.field, "location_source")) {</span><br><span>             ast_str_append(buf, len, "%s", eprofile->location_source);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (ast_strings_equal(args.field, "notes")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_str_append(buf, len, "%s", eprofile->notes);</span><br><span>        } else if (ast_strings_equal(args.field, "location_info")) {</span><br><span>               varlist_to_str(eprofile->location_info, buf, len);</span><br><span>        } else if (ast_strings_equal(args.field, "location_info_refinement")) {</span><br><span>@@ -129,41 +108,37 @@</span><br><span>            varlist_to_str(eprofile->effective_location, buf, len);</span><br><span>   } else if (ast_strings_equal(args.field, "usage_rules")) {</span><br><span>                 varlist_to_str(eprofile->usage_rules, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (ast_strings_equal(args.field, "confidence")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           varlist_to_str(eprofile->confidence, buf, len);</span><br><span>   } else {</span><br><span>             ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field);</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3");</span><br><span>    }</span><br><span> </span><br><span>        ao2_ref(eprofile, -1);</span><br><span>       return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define TEST_ENUM_VALUE(_cmd, _ep, _field, _value) \</span><br><span style="color: hsl(120, 100%, 40%);">+#define TEST_ENUM_VALUE(_chan_name, _ep, _field, _value) \</span><br><span> ({ \</span><br><span>   enum ast_geoloc_ ## _field v; \</span><br><span style="color: hsl(0, 100%, 40%);">- if (!_ep) { \</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(LOG_ERROR, "%s: Field %s requires a valid index\n", _cmd, #_field); \</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1; \</span><br><span style="color: hsl(0, 100%, 40%);">-    } \</span><br><span style="color: hsl(0, 100%, 40%);">-     v = geoloc_ ## _field ## _str_to_enum(_value); \</span><br><span style="color: hsl(120, 100%, 40%);">+      v = ast_geoloc_ ## _field ## _str_to_enum(_value); \</span><br><span>         if (v == AST_GEOLOC_INVALID_VALUE) { \</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_log(LOG_ERROR, "%s: %s '%s' is invalid\n", _cmd, #_field, value); \</span><br><span style="color: hsl(0, 100%, 40%);">-               return -1; \</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "%s: %s '%s' is invalid\n", _chan_name, #_field, value); \</span><br><span style="color: hsl(120, 100%, 40%);">+               pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); \</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0; \</span><br><span>  } \</span><br><span>  _ep->_field = v; \</span><br><span> })</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define TEST_VARLIST(_cmd, _ep, _field, _value) \</span><br><span style="color: hsl(120, 100%, 40%);">+#define TEST_VARLIST(_chan_name, _ep, _field, _value) \</span><br><span> ({ \</span><br><span>    struct ast_variable *_list; \</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!_ep) { \</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(LOG_ERROR, "%s: Field %s requires a valid index\n", _cmd, #_field); \</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1; \</span><br><span style="color: hsl(0, 100%, 40%);">-    } \</span><br><span>  _list = ast_variable_list_from_quoted_string(_value, ",", "=", "\"" ); \</span><br><span>  if (!_list) { \</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_log(LOG_ERROR, "%s: %s '%s' is malformed or contains invalid values", _cmd, #_field, _value); \</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1; \</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_ERROR, "%s: %s '%s' is malformed or contains invalid values", _chan_name, #_field, _value); \</span><br><span style="color: hsl(120, 100%, 40%);">+           pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3"); \</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0; \</span><br><span>  } \</span><br><span>  ast_variables_destroy(_ep->_field); \</span><br><span>     _ep->_field = _list; \</span><br><span>@@ -173,105 +148,106 @@</span><br><span>   const char *value)</span><br><span> {</span><br><span>     char *parsed_data = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_datastore *ds;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *chan_name = ast_channel_name(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_datastore *ds; /* Reminder: datastores aren't ao2 objects */</span><br><span>  RAII_VAR(struct ast_geoloc_eprofile *, eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-    int profile_count = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  int index = -1;</span><br><span> </span><br><span>  AST_DECLARE_APP_ARGS(args,</span><br><span>           AST_APP_ARG(field);</span><br><span style="color: hsl(0, 100%, 40%);">-             AST_APP_ARG(index);</span><br><span>  );</span><br><span> </span><br><span>       /* Check for zero arguments */</span><br><span>       if (ast_strlen_zero(parsed_data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", chan_name);</span><br><span style="color: hsl(120, 100%, 40%);">+               pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span> </span><br><span>        AST_STANDARD_APP_ARGS(args, parsed_data);</span><br><span> </span><br><span>        if (ast_strlen_zero(args.field)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_log(LOG_ERROR, "%s: Cannot call without a field to set\n", cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</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%);">-       if (!ast_strlen_zero(args.index)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (sscanf(args.index, "%30d", &index) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_log(LOG_ERROR, "%s: profile_index '%s' is invalid\n", cmd, args.index);</span><br><span style="color: hsl(0, 100%, 40%);">-                   return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_ERROR, "%s: Cannot call without a field to set\n", chan_name);</span><br><span style="color: hsl(120, 100%, 40%);">+          pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-1");</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span> </span><br><span>        ds = ast_geoloc_datastore_find(chan);</span><br><span>        if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_log(LOG_WARNING, "%s: There are no geoloc profiles on this channel\n", cmd);</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            ds = ast_geoloc_datastore_create(ast_channel_name(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!ds) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_log(LOG_WARNING, "%s: Unable to create geolocation datastore\n", chan_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                    pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");</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%);">+             ast_channel_datastore_add(chan, ds);</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (index >= 0 && index < profile_count) {</span><br><span style="color: hsl(0, 100%, 40%);">-                eprofile = ast_geoloc_datastore_get_eprofile(ds, index);</span><br><span style="color: hsl(120, 100%, 40%);">+      eprofile = ast_geoloc_datastore_get_eprofile(ds, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+              int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+               eprofile = ast_geoloc_eprofile_alloc(chan_name);</span><br><span>             if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_log(LOG_ERROR, "%s: Internal Error.  Profile at index %d couldn't be retrieved.\n", cmd, index);</span><br><span style="color: hsl(0, 100%, 40%);">-                      return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_log(LOG_ERROR, "%s: Could not allocate eprofile\n", chan_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                 pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return 0;</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-       } else if (index >= profile_count) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_log(LOG_ERROR, "%s: index %d is out of range 0 -> %d\n", cmd, index, profile_count);</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (ast_strings_equal(args.field, "inheritable")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   ast_geoloc_datastore_set_inheritance(ds, ast_true(value));</span><br><span style="color: hsl(0, 100%, 40%);">-              } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_log(LOG_ERROR, "%s: Field '%s' is not valid or requires a profile index\n", cmd, args.field);</span><br><span style="color: hsl(0, 100%, 40%);">-                     return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_log(LOG_ERROR, "%s: Could not add eprofile to datastore\n", chan_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                 pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-2");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return 0;</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_strings_equal(args.field, "location_reference")) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ast_strings_equal(args.field, "inheritable")) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_geoloc_datastore_set_inheritance(ds, ast_true(value));</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (ast_strings_equal(args.field, "location_reference")) {</span><br><span>          struct ast_geoloc_location *loc = ast_geoloc_get_location(value);</span><br><span>            ao2_cleanup(loc);</span><br><span>            if (!loc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     ast_log(LOG_ERROR, "%s: Location reference '%s' doesn't exist\n", cmd, value);</span><br><span style="color: hsl(0, 100%, 40%);">-                    return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_log(LOG_ERROR, "%s: Location reference '%s' doesn't exist\n", chan_name, value);</span><br><span style="color: hsl(120, 100%, 40%);">+                    pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3");</span><br><span style="color: hsl(120, 100%, 40%);">+                     return 0;</span><br><span>            }</span><br><span>            ast_string_field_set(eprofile, location_reference, value);</span><br><span>   } else if (ast_strings_equal(args.field, "method")) {</span><br><span>              ast_string_field_set(eprofile, method, value);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      } else if (ast_strings_equal(args.field, "geolocation_routing")) {</span><br><span style="color: hsl(0, 100%, 40%);">-            eprofile->geolocation_routing = ast_true(value);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (ast_strings_equal(args.field, "allow_routing_use")) {</span><br><span style="color: hsl(120, 100%, 40%);">+            eprofile->allow_routing_use = ast_true(value);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   } else if (ast_strings_equal(args.field, "profile_action")) {</span><br><span style="color: hsl(0, 100%, 40%);">-         TEST_ENUM_VALUE(cmd, eprofile, action, value);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (ast_strings_equal(args.field, "profile_precedence")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           TEST_ENUM_VALUE(chan_name, eprofile, precedence, value);</span><br><span> </span><br><span>         } else if (ast_strings_equal(args.field, "format")) {</span><br><span style="color: hsl(0, 100%, 40%);">-         TEST_ENUM_VALUE(cmd, eprofile, format, value);</span><br><span style="color: hsl(120, 100%, 40%);">+                TEST_ENUM_VALUE(chan_name, eprofile, format, value);</span><br><span> </span><br><span>     } else if (ast_strings_equal(args.field, "pidf_element")) {</span><br><span style="color: hsl(0, 100%, 40%);">-           TEST_ENUM_VALUE(cmd, eprofile, pidf_element, value);</span><br><span style="color: hsl(120, 100%, 40%);">+          TEST_ENUM_VALUE(chan_name, eprofile, pidf_element, value);</span><br><span> </span><br><span>       } else if (ast_strings_equal(args.field, "location_info")) {</span><br><span style="color: hsl(0, 100%, 40%);">-          TEST_VARLIST(cmd, eprofile, location_info, value);</span><br><span style="color: hsl(120, 100%, 40%);">+            TEST_VARLIST(chan_name, eprofile, location_info, value);</span><br><span>     } else if (ast_strings_equal(args.field, "location_source")) {</span><br><span>             ast_string_field_set(eprofile, location_source, value);</span><br><span>      } else if (ast_strings_equal(args.field, "location_info_refinement")) {</span><br><span style="color: hsl(0, 100%, 40%);">-               TEST_VARLIST(cmd, eprofile, location_refinement, value);</span><br><span style="color: hsl(120, 100%, 40%);">+              TEST_VARLIST(chan_name, eprofile, location_refinement, value);</span><br><span>       } else if (ast_strings_equal(args.field, "location_variables")) {</span><br><span style="color: hsl(0, 100%, 40%);">-             TEST_VARLIST(cmd, eprofile, location_variables, value);</span><br><span style="color: hsl(120, 100%, 40%);">+               TEST_VARLIST(chan_name, eprofile, location_variables, value);</span><br><span>        } else if (ast_strings_equal(args.field, "effective_location")) {</span><br><span style="color: hsl(0, 100%, 40%);">-             TEST_VARLIST(cmd, eprofile, effective_location, value);</span><br><span style="color: hsl(120, 100%, 40%);">+               TEST_VARLIST(chan_name, eprofile, effective_location, value);</span><br><span>        } else if (ast_strings_equal(args.field, "usage_rules")) {</span><br><span style="color: hsl(0, 100%, 40%);">-            TEST_VARLIST(cmd, eprofile, usage_rules, value);</span><br><span style="color: hsl(120, 100%, 40%);">+              TEST_VARLIST(chan_name, eprofile, usage_rules, value);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (ast_strings_equal(args.field, "confidence")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           TEST_VARLIST(chan_name, eprofile, confidence, value);</span><br><span>        } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", cmd, args.field);</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_ERROR, "%s: Field '%s' is not valid\n", chan_name, args.field);</span><br><span style="color: hsl(120, 100%, 40%);">+         pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "-3");</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span> </span><br><span>        ast_geoloc_eprofile_refresh_location(eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+       pbx_builtin_setvar_helper(chan, "GEOLOCPROFILESTATUS", "0");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -281,155 +257,8 @@</span><br><span>   .write = geoloc_profile_write,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define profile_create "GeolocProfileCreate"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int geoloc_eprofile_create(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    char *parsed_data = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_datastore *ds;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_geoloc_eprofile * eprofile;</span><br><span style="color: hsl(0, 100%, 40%);">-  int profile_count = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  int index = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct ast_str *new_size;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_APP_ARG(id);</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_APP_ARG(index);</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%);">-      /* Check for zero arguments */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (ast_strlen_zero(parsed_data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", profile_create);</span><br><span style="color: hsl(0, 100%, 40%);">-            return -1;</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%);">-       AST_STANDARD_APP_ARGS(args, parsed_data);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_strlen_zero(args.id)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_log(LOG_ERROR, "%s: Cannot call without an id field\n", profile_create);</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</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%);">-       if (!ast_strlen_zero(args.index)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (sscanf(args.index, "%30d", &index) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_log(LOG_ERROR, "%s: profile_index '%s' is invalid\n", profile_create, args.index);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return -1;</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%);">-                index = -1;</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%);">-       ds = ast_geoloc_datastore_find(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_log(LOG_WARNING, "%s: There are no geoloc profiles on this channel\n", profile_create);</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1;</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%);">-       profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">-  if (index < -1 || index >= profile_count) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_log(LOG_ERROR, "%s: Invalid insert_before index '%d'.  It must be 0 to insert at the beginning of the list or -1 to append to the end of the list\n", profile_create, index);</span><br><span style="color: hsl(0, 100%, 40%);">-             return -1;</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%);">-       eprofile = ast_geoloc_eprofile_alloc(args.id);</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "%s: Could not allocate eprofile '%s'\n", profile_create, args.id);</span><br><span style="color: hsl(0, 100%, 40%);">-                return -1;</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%);">-       ds = ast_geoloc_datastore_find(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ds = ast_geoloc_datastore_create_from_eprofile(eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      ao2_ref(eprofile, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_log(LOG_ERROR, "%s: Could not create datastore for eprofile '%s'\n", profile_create, args.id);</span><br><span style="color: hsl(0, 100%, 40%);">-                    return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-               rc = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_channel_datastore_add(chan, ds);</span><br><span style="color: hsl(0, 100%, 40%);">-    } else if (index < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (rc <= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ao2_ref(eprofile, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_log(LOG_ERROR, "%s: Could not add eprofile '%s' to datastore\n", profile_create, args.id);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return -1;</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%);">-                rc = ast_geoloc_datastore_insert_eprofile(ds, eprofile, index);</span><br><span style="color: hsl(0, 100%, 40%);">-         if (rc <= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ao2_ref(eprofile, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_log(LOG_ERROR, "%s: Could not insert eprofile '%s' to datastore\n", profile_create, args.id);</span><br><span style="color: hsl(0, 100%, 40%);">-                     return -1;</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%);">-       new_size = ast_str_alloca(16);</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_str_append(&new_size, 0, "%d", rc);</span><br><span style="color: hsl(0, 100%, 40%);">-   pbx_builtin_setvar_helper(chan, "GEOLOC_PROFILE_COUNT", ast_str_buffer(new_size));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define profile_delete "GeolocProfileDelete"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int geoloc_eprofile_delete(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  char *parsed_data = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_datastore *ds;</span><br><span style="color: hsl(0, 100%, 40%);">-       int profile_count = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  int index = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_str *new_size;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_APP_ARG(index);</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%);">-      /* Check for zero arguments */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (ast_strlen_zero(parsed_data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(LOG_ERROR, "%s: Cannot call without arguments\n", profile_delete);</span><br><span style="color: hsl(0, 100%, 40%);">-            return -1;</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%);">-       AST_STANDARD_APP_ARGS(args, parsed_data);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!ast_strlen_zero(args.index)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (sscanf(args.index, "%30d", &index) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_log(LOG_ERROR, "%s: profile_index '%s' is invalid\n", profile_delete, args.index);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return -1;</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, "%s: A profile_index is required\n", profile_delete);</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</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%);">-       ds = ast_geoloc_datastore_find(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_log(LOG_WARNING, "%s: There are no geoloc profiles on this channel\n", profile_delete);</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1;</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%);">-       profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">-  if (index < -1 || index >= profile_count) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_log(LOG_ERROR, "%s: Invalid profile_index '%d'.  It must be between 0 and %d\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  profile_create, index, profile_count - 1);</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</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%);">-       ast_geoloc_datastore_delete_eprofile(ds, index);</span><br><span style="color: hsl(0, 100%, 40%);">-        profile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  new_size = ast_str_alloca(16);</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_str_append(&new_size, 0, "%d", profile_count);</span><br><span style="color: hsl(0, 100%, 40%);">-        pbx_builtin_setvar_helper(chan, "GEOLOC_PROFILE_COUNT", ast_str_buffer(new_size));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int geoloc_dialplan_unload(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_unregister_application(profile_delete);</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_unregister_application(profile_create);</span><br><span>  ast_custom_function_unregister(&geoloc_function);</span><br><span> </span><br><span>    return AST_MODULE_LOAD_SUCCESS;</span><br><span>@@ -440,12 +269,6 @@</span><br><span>       int res = 0;</span><br><span> </span><br><span>     res = ast_custom_function_register(&geoloc_function);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (res == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         res = ast_register_application_xml(profile_create, geoloc_eprofile_create);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (res == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         res = ast_register_application_xml(profile_delete, geoloc_eprofile_delete);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span> </span><br><span>        return res == 0 ? AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;</span><br><span> }</span><br><span>diff --git a/res/res_geolocation/geoloc_doc.xml b/res/res_geolocation/geoloc_doc.xml</span><br><span>index 5c8bf79..2e28f7e 100644</span><br><span>--- a/res/res_geolocation/geoloc_doc.xml</span><br><span>+++ b/res/res_geolocation/geoloc_doc.xml</span><br><span>@@ -94,6 +94,34 @@</span><br><span>                                          </enumlist></span><br><span>                                    </description></span><br><span>                                 </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="confidence" default=""></span><br><span style="color: hsl(120, 100%, 40%);">+                                 <synopsis>Level of confidence</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <description></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <para>This is a rarely used field in the specification that would</span><br><span style="color: hsl(120, 100%, 40%);">+                                               indicate the confidence in the location specified.  See RFC7459</span><br><span style="color: hsl(120, 100%, 40%);">+                                               for exact details.</span><br><span style="color: hsl(120, 100%, 40%);">+                                            </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                         <para></span><br><span style="color: hsl(120, 100%, 40%);">+                                          Sub-parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+                                               </para></span><br><span style="color: hsl(120, 100%, 40%);">+                                         <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                              <enum name="pdf"></span><br><span style="color: hsl(120, 100%, 40%);">+                                             <para>One of:</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                              <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                              <enum name="unknown"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                                <enum name="normal"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                         <enum name="rectangular"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                            </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                             </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                                         <enum name="value"></span><br><span style="color: hsl(120, 100%, 40%);">+                                           <para>A percentage indicating the confidence.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                              </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                                         </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                     </description></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+                                              <ref type="link">https://www.rfc-editor.org/rfc/rfc7459</ref></span><br><span style="color: hsl(120, 100%, 40%);">+                                   </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+                             </configOption></span><br><span>                        </configObject></span><br><span>                        <configObject name="profile"></span><br><span>                                <synopsis>Profile</synopsis></span><br><span>@@ -144,7 +172,11 @@</span><br><span>                                              any recipients.</para></span><br><span>                                         </description></span><br><span>                                 </configOption></span><br><span style="color: hsl(0, 100%, 40%);">-                           <configOption name="profile_action" default="discard_incoming"></span><br><span style="color: hsl(120, 100%, 40%);">+                             <configOption name="allow_routing_use"></span><br><span style="color: hsl(120, 100%, 40%);">+                                       <synopsis>Sets the value of the Geolocation-Routing header.</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                            </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                               <configOption name="profile_precedence" default="discard_incoming"></span><br><span>                                        <synopsis>Determine which profile on a channel should be used</synopsis></span><br><span>                                         <description></span><br><span>                                          <enumlist></span><br><span>@@ -180,56 +212,47 @@</span><br><span>             </synopsis></span><br><span>            <syntax></span><br><span>                       <parameter name="field" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">-                              <para>The profile field to operate on.</para></span><br><span style="color: hsl(0, 100%, 40%);">-                       </parameter></span><br><span style="color: hsl(0, 100%, 40%);">-                      <parameter name="profile_index" required="false"></span><br><span style="color: hsl(0, 100%, 40%);">-                             <para>The index of the profile to operate on.  Not required for the special fields.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                                <para>The profile field to operate on. The following fields from the</span><br><span style="color: hsl(120, 100%, 40%);">+                            Location and Profile objects are supported.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                              <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                                      <enum name="id"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <enum name="location_reference"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <enum name="method"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                 <enum name="allow_routing_use"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                      <enum name="profile_precedence"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <enum name="format"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                 <enum name="pidf_element"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                   <enum name="location_source"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                        <enum name="notes"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <enum name="location_info"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                  <enum name="location_info_refinement"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                       <enum name="location_variables"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <enum name="effective_location"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                     <enum name="usage_rules"/></span><br><span style="color: hsl(120, 100%, 40%);">+                                    <enum name="confidence"/></span><br><span style="color: hsl(120, 100%, 40%);">+                             </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                             <para>Additionally, the <literal>inheritable</literal> field may be</span><br><span style="color: hsl(120, 100%, 40%);">+                         set to <literal>true</literal> or <literal>false</literal> to control</span><br><span style="color: hsl(120, 100%, 40%);">+                         whether the profile will be passed to the outgoing channel.</span><br><span style="color: hsl(120, 100%, 40%);">+                           </para></span><br><span>                        </parameter></span><br><span>           </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+               <description><para></span><br><span style="color: hsl(120, 100%, 40%);">+               When used to set a field on a profile, if the profile doesn't already exist, a new</span><br><span style="color: hsl(120, 100%, 40%);">+                one will be created automatically.</span><br><span style="color: hsl(120, 100%, 40%);">+            </para></span><br><span style="color: hsl(120, 100%, 40%);">+         <para></span><br><span style="color: hsl(120, 100%, 40%);">+          The <literal>${GEOLOCPROFILESTATUS}</literal> channel variable will be set with</span><br><span style="color: hsl(120, 100%, 40%);">+           a return code indicating the result of the operation.  Possible values are:</span><br><span style="color: hsl(120, 100%, 40%);">+           </para></span><br><span style="color: hsl(120, 100%, 40%);">+         <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="0"><para>Success</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+                  <enum name="-1"><para>No or not enough parameters were supplied</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+                       <enum name="-2"><para>There was an internal error finding or creating a profile</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+                       <enum name="-3"><para>There was an issue specific to the field specified</span><br><span style="color: hsl(120, 100%, 40%);">+                        (value not valid or field name not found)</para></enum></span><br><span style="color: hsl(120, 100%, 40%);">+           </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+             </description></span><br><span>         </function></span><br><span style="color: hsl(0, 100%, 40%);">-       <application name="GeolocProfileCreate" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">-             <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-                        Create a new, empty Geolocation Profile on a channel</span><br><span style="color: hsl(0, 100%, 40%);">-            </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-               <syntax></span><br><span style="color: hsl(0, 100%, 40%);">-                  <parameter name="id" required="true"><para></span><br><span style="color: hsl(0, 100%, 40%);">-                             The id of the new profile.</span><br><span style="color: hsl(0, 100%, 40%);">-                      </para></parameter></span><br><span style="color: hsl(0, 100%, 40%);">-                 <parameter name="profile_index" required="false"><para></span><br><span style="color: hsl(0, 100%, 40%);">-                  The position at which to insert the new eprofile.</span><br><span style="color: hsl(0, 100%, 40%);">-                       Existing profiles will be moved forward to make room.</span><br><span style="color: hsl(0, 100%, 40%);">-                   Leave empty to append to the end of the list.</span><br><span style="color: hsl(0, 100%, 40%);">-                  </para></parameter></span><br><span style="color: hsl(0, 100%, 40%);">-         </syntax></span><br><span style="color: hsl(0, 100%, 40%);">-         <description></span><br><span style="color: hsl(0, 100%, 40%);">-                     <para>This application adds a new, empty Geolocation Profile to a channel.</para></span><br><span style="color: hsl(0, 100%, 40%);">-                   <para>The following variable is set:</para></span><br><span style="color: hsl(0, 100%, 40%);">-                 <variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-                            <variable name="GEOLOC_PROFILE_COUNT"></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <para>The number of profiles on the channel after the new one is created</para></span><br><span style="color: hsl(0, 100%, 40%);">-                             </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                       </variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-           </description></span><br><span style="color: hsl(0, 100%, 40%);">-    </application></span><br><span style="color: hsl(0, 100%, 40%);">-    <application name="GeolocProfileDelete" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">-             <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-                        Delete a Geolocation Profile from a channel</span><br><span style="color: hsl(0, 100%, 40%);">-             </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-               <syntax></span><br><span style="color: hsl(0, 100%, 40%);">-                  <parameter name="profile_index" required="true"><para></span><br><span style="color: hsl(0, 100%, 40%);">-                   The position of the profile to be deleted</span><br><span style="color: hsl(0, 100%, 40%);">-                       Existing profiles will be moved back.</span><br><span style="color: hsl(0, 100%, 40%);">-                  </para></parameter></span><br><span style="color: hsl(0, 100%, 40%);">-         </syntax></span><br><span style="color: hsl(0, 100%, 40%);">-         <description></span><br><span style="color: hsl(0, 100%, 40%);">-                     <para>This application deletes a Geolocation Profile from a channel.</para></span><br><span style="color: hsl(0, 100%, 40%);">-                 <para>The following variable is set:</para></span><br><span style="color: hsl(0, 100%, 40%);">-                 <variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-                            <variable name="GEOLOC_PROFILE_COUNT"></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <para>The number of profiles left on the channel after the delete.</para></span><br><span style="color: hsl(0, 100%, 40%);">-                           </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                       </variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-           </description></span><br><span style="color: hsl(0, 100%, 40%);">-    </application></span><br><span> </docs></span><br><span> </span><br><span>diff --git a/res/res_geolocation/geoloc_eprofile.c b/res/res_geolocation/geoloc_eprofile.c</span><br><span>index af0e89c..bfba2d2 100644</span><br><span>--- a/res/res_geolocation/geoloc_eprofile.c</span><br><span>+++ b/res/res_geolocation/geoloc_eprofile.c</span><br><span>@@ -63,6 +63,7 @@</span><br><span>       ast_variables_destroy(eprofile->location_variables);</span><br><span>      ast_variables_destroy(eprofile->effective_location);</span><br><span>      ast_variables_destroy(eprofile->usage_rules);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_variables_destroy(eprofile->confidence);</span><br><span> }</span><br><span> </span><br><span> struct ast_geoloc_eprofile *ast_geoloc_eprofile_alloc(const char *name)</span><br><span>@@ -79,8 +80,12 @@</span><br><span> int ast_geoloc_eprofile_refresh_location(struct ast_geoloc_eprofile *eprofile)</span><br><span> {</span><br><span>      struct ast_geoloc_location *loc = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *temp_locinfo = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_variable *temp_effloc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      RAII_VAR(struct ast_variable *, temp_locinfo, NULL, ast_variables_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+   RAII_VAR(struct ast_variable *, temp_effloc, NULL, ast_variables_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+    RAII_VAR(struct ast_variable *, temp_confidence, NULL, ast_variables_destroy);</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *method = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *location_source = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   enum ast_geoloc_format format;</span><br><span>       struct ast_variable *var;</span><br><span>    int rc = 0;</span><br><span> </span><br><span>@@ -96,20 +101,32 @@</span><br><span>                       return -1;</span><br><span>           }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           eprofile->format = loc->format;</span><br><span style="color: hsl(120, 100%, 40%);">+         format = loc->format;</span><br><span style="color: hsl(120, 100%, 40%);">+              method = loc->method;</span><br><span style="color: hsl(120, 100%, 40%);">+              location_source = loc->location_source;</span><br><span>           rc = DUP_VARS(temp_locinfo, loc->location_info);</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_string_field_set(eprofile, method, loc->method);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        rc = DUP_VARS(temp_confidence, loc->confidence);</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span>            ao2_ref(loc, -1);</span><br><span>            if (rc != 0) {</span><br><span>                       return -1;</span><br><span>           }</span><br><span>    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                temp_locinfo = eprofile->location_info;</span><br><span style="color: hsl(120, 100%, 40%);">+            format = eprofile->format;</span><br><span style="color: hsl(120, 100%, 40%);">+         method = eprofile->method;</span><br><span style="color: hsl(120, 100%, 40%);">+         location_source = eprofile->location_source;</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = DUP_VARS(temp_locinfo, eprofile->location_info);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        rc = DUP_VARS(temp_confidence, eprofile->confidence);</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%);">+                        return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span>    }</span><br><span> </span><br><span>        rc = DUP_VARS(temp_effloc, temp_locinfo);</span><br><span>    if (rc != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_variables_destroy(temp_locinfo);</span><br><span>                 return -1;</span><br><span>   }</span><br><span> </span><br><span>@@ -117,8 +134,6 @@</span><br><span>          for (var = eprofile->location_refinement; var; var = var->next) {</span><br><span>                      struct ast_variable *newvar = ast_variable_new(var->name, var->value, "");</span><br><span>                   if (!newvar) {</span><br><span style="color: hsl(0, 100%, 40%);">-                          ast_variables_destroy(temp_locinfo);</span><br><span style="color: hsl(0, 100%, 40%);">-                            ast_variables_destroy(temp_effloc);</span><br><span>                          return -1;</span><br><span>                   }</span><br><span>                    if (ast_variable_list_replace(&temp_effloc, newvar)) {</span><br><span>@@ -127,10 +142,16 @@</span><br><span>           }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ eprofile->format = format;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(eprofile, method, method);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_string_field_set(eprofile, location_source, location_source);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  ast_variables_destroy(eprofile->location_info);</span><br><span>   eprofile->location_info = temp_locinfo;</span><br><span style="color: hsl(120, 100%, 40%);">+    temp_locinfo = NULL;</span><br><span>         ast_variables_destroy(eprofile->effective_location);</span><br><span>      eprofile->effective_location = temp_effloc;</span><br><span style="color: hsl(120, 100%, 40%);">+        temp_effloc = NULL;</span><br><span> </span><br><span>      return 0;</span><br><span> }</span><br><span>@@ -153,7 +174,7 @@</span><br><span>         }</span><br><span> </span><br><span>        ao2_lock(profile);</span><br><span style="color: hsl(0, 100%, 40%);">-      eprofile->geolocation_routing = profile->geolocation_routing;</span><br><span style="color: hsl(120, 100%, 40%);">+   eprofile->allow_routing_use = profile->allow_routing_use;</span><br><span>      eprofile->pidf_element = profile->pidf_element;</span><br><span> </span><br><span>    rc = ast_string_field_set(eprofile, location_reference, profile->location_reference);</span><br><span>@@ -175,7 +196,7 @@</span><br><span>               return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   eprofile->action = profile->action;</span><br><span style="color: hsl(120, 100%, 40%);">+     eprofile->precedence = profile->precedence;</span><br><span>    ao2_unlock(profile);</span><br><span> </span><br><span>     if (ast_geoloc_eprofile_refresh_location(eprofile) != 0) {</span><br><span>@@ -301,20 +322,20 @@</span><br><span> </span><br><span> </span><br><span> const char *ast_geoloc_eprofile_to_uri(struct ast_geoloc_eprofile *eprofile,</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_channel *chan, struct ast_str **buf, const char *ref_string)</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_channel *chan, struct ast_str **buf, const char *ref_str)</span><br><span> {</span><br><span>    const char *uri = NULL;</span><br><span>      struct ast_variable *resolved = NULL;</span><br><span>        char *result;</span><br><span>        int we_created_buf = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!eprofile || !buf) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!eprofile || !buf || !chan) {</span><br><span>            return NULL;</span><br><span>         }</span><br><span> </span><br><span>        if (eprofile->format != AST_GEOLOC_FORMAT_URI) {</span><br><span>          ast_log(LOG_ERROR, "%s: '%s' is not a URI profile.  It's '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                 ref_string, eprofile->id, geoloc_format_to_name(eprofile->format));</span><br><span style="color: hsl(120, 100%, 40%);">+                     ref_str, eprofile->id, ast_geoloc_format_to_name(eprofile->format));</span><br><span>           return NULL;</span><br><span>         }</span><br><span> </span><br><span>@@ -330,7 +351,7 @@</span><br><span> </span><br><span>      if (ast_strlen_zero(result)) {</span><br><span>               ast_log(LOG_ERROR, "%s: '%s' is a URI profile but had no, or an empty, 'URI' entry in location_info\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                       ref_string, eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+                 ref_str, eprofile->id);</span><br><span>           return NULL;</span><br><span>         }</span><br><span> </span><br><span>@@ -353,14 +374,14 @@</span><br><span>        return ast_str_buffer(*buf);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_variable *var_list_from_node(struct ast_xml_node *node, const char *reference_string)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_variable *var_list_from_node(struct ast_xml_node *node,</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *ref_str)</span><br><span> {</span><br><span>    struct ast_variable *list = NULL;</span><br><span>    struct ast_xml_node *container;</span><br><span>      struct ast_xml_node *child;</span><br><span>  struct ast_variable *var;</span><br><span style="color: hsl(0, 100%, 40%);">-       RAII_VAR(struct ast_str *, buf, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-        SCOPE_ENTER(3, "%s\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+   SCOPE_ENTER(3, "%s\n", ref_str);</span><br><span> </span><br><span>       container = ast_xml_node_get_children(node);</span><br><span>         for (child = container; child; child = ast_xml_node_get_next(child)) {</span><br><span>@@ -370,168 +391,296 @@</span><br><span> </span><br><span>                 if (uom) {</span><br><span>                   /* '20 radians\0' */</span><br><span style="color: hsl(0, 100%, 40%);">-                    char *newval = ast_malloc(strlen(value) + 1 + strlen(uom) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                       char newval[strlen(value) + 1 + strlen(uom) + 1];</span><br><span>                    sprintf(newval, "%s %s", value, uom);</span><br><span>                      var = ast_variable_new(name, newval, "");</span><br><span style="color: hsl(0, 100%, 40%);">-                     ast_free(newval);</span><br><span>            } else {</span><br><span>                     var = ast_variable_new(name, value, "");</span><br><span>           }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         ast_xml_free_text(value);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_xml_free_attr(uom);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>            if (!var) {</span><br><span>                  ast_variables_destroy(list);</span><br><span style="color: hsl(0, 100%, 40%);">-                    SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+                   SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</span><br><span>           }</span><br><span>            ast_variable_list_append(&list, var);</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_variable_list_join(list, ", ", "=", "\"", &buf);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct ast_str *buf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_variable_list_join(list, ", ", "=", "\"", &buf);</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_trace(5, "%s: Result: %s\n", ref_str, ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_free(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   SCOPE_EXIT_RTN_VALUE(list, "%s: Done. %s\n", reference_string, ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+        SCOPE_EXIT_RTN_VALUE(list, "%s: Done\n", ref_str);</span><br><span> }</span><br><span> </span><br><span> static struct ast_variable *var_list_from_loc_info(struct ast_xml_node *locinfo,</span><br><span style="color: hsl(0, 100%, 40%);">-       enum ast_geoloc_format format, const char *reference_string)</span><br><span style="color: hsl(120, 100%, 40%);">+  enum ast_geoloc_format format, const char *ref_str)</span><br><span> {</span><br><span>     struct ast_variable *list = NULL;</span><br><span>    struct ast_xml_node *container;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *var;</span><br><span style="color: hsl(0, 100%, 40%);">-       RAII_VAR(struct ast_str *, buf, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-        SCOPE_ENTER(3, "%s\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_variable *var = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *attr;</span><br><span style="color: hsl(120, 100%, 40%);">+     SCOPE_ENTER(3, "%s\n", ref_str);</span><br><span> </span><br><span>       container = ast_xml_node_get_children(locinfo);</span><br><span>      if (format == AST_GEOLOC_FORMAT_CIVIC_ADDRESS) {</span><br><span style="color: hsl(0, 100%, 40%);">-                var = ast_variable_new("lang", ast_xml_get_attribute(container, "lang"), "");</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!var) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+           attr = ast_xml_get_attribute(container, "lang");</span><br><span style="color: hsl(120, 100%, 40%);">+            if (attr) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   var = ast_variable_new("lang", attr, "");</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_xml_free_attr(attr);</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (!var) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_variable_list_append(&list, var);</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_variable_list_append(&list, var);</span><br><span>    } else {</span><br><span>             var = ast_variable_new("shape", ast_xml_node_get_name(container), "");</span><br><span>           if (!var) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+                   SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</span><br><span>           }</span><br><span>            ast_variable_list_append(&list, var);</span><br><span style="color: hsl(0, 100%, 40%);">-               var = ast_variable_new("crs", ast_xml_get_attribute(container, "srsName"), "");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               attr = ast_xml_get_attribute(container, "srsName");</span><br><span style="color: hsl(120, 100%, 40%);">+         var = ast_variable_new("crs", attr, "");</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_xml_free_attr(attr);</span><br><span>             if (!var) {</span><br><span>                  ast_variables_destroy(list);</span><br><span style="color: hsl(0, 100%, 40%);">-                    SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+                   SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</span><br><span>           }</span><br><span>            ast_variable_list_append(&list, var);</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_variable_list_append(&list, var_list_from_node(container, reference_string));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_variable_list_append(&list, var_list_from_node(container, ref_str));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ast_variable_list_join(list, ", ", "=", "\"", &buf);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct ast_str *buf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_variable_list_join(list, ", ", "=", "\"", &buf);</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_trace(5, "%s: Result: %s\n", ref_str, ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_free(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   SCOPE_EXIT_RTN_VALUE(list, "%s: Done. %s\n", reference_string, ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+        SCOPE_EXIT_RTN_VALUE(list, "%s: Done\n", ref_str);</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_variable *var_list_from_confidence(struct ast_xml_node *confidence,</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *ref_str)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_variable *list = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *pdf;</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *value;</span><br><span style="color: hsl(120, 100%, 40%);">+    SCOPE_ENTER(3, "%s\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!confidence) {</span><br><span style="color: hsl(120, 100%, 40%);">+            SCOPE_EXIT_RTN_VALUE(NULL, "%s: No confidence\n", ref_str);</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%);">+   pdf = ast_xml_get_attribute(confidence, "pdf");</span><br><span style="color: hsl(120, 100%, 40%);">+     var = ast_variable_new("pdf", S_OR(pdf, "unknown"), "");</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_xml_free_attr(pdf);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!var) {</span><br><span style="color: hsl(120, 100%, 40%);">+           SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_variable_list_append(&list, var);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   value = ast_xml_get_text(confidence);</span><br><span style="color: hsl(120, 100%, 40%);">+ var = ast_variable_new("value", S_OR(value, "95"), "");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_xml_free_text(value);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!var) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_variables_destroy(list);</span><br><span style="color: hsl(120, 100%, 40%);">+          SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_variable_list_append(&list, var);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct ast_str *buf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_variable_list_join(list, ", ", "=", "\"", &buf);</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_trace(5, "%s: Result: %s\n", ref_str, ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_free(buf);</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%);">+   SCOPE_EXIT_RTN_VALUE(list, "%s: Done\n", ref_str);</span><br><span> }</span><br><span> </span><br><span> static struct ast_geoloc_eprofile *geoloc_eprofile_create_from_xslt_result(</span><br><span style="color: hsl(0, 100%, 40%);">-    struct ast_xml_doc *result_doc,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *reference_string)</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_xml_doc *result_doc, const char *ref_str)</span><br><span> {</span><br><span>    struct ast_geoloc_eprofile *eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * None of the ast_xml_nodes needs to be freed</span><br><span style="color: hsl(120, 100%, 40%);">+         * because they're just pointers into result_doc.</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span>  struct ast_xml_node *presence = NULL;</span><br><span>        struct ast_xml_node *pidf_element = NULL;</span><br><span>    struct ast_xml_node *location_info = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_xml_node *confidence = NULL;</span><br><span>      struct ast_xml_node *usage_rules = NULL;</span><br><span>     struct ast_xml_node *method = NULL;</span><br><span>  struct ast_xml_node *note_well = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-  char *doc_str;</span><br><span style="color: hsl(0, 100%, 40%);">-  int doc_len;</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *id;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *format_str;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Like nodes, names of nodes are just</span><br><span style="color: hsl(120, 100%, 40%);">+         * pointers into result_doc and don't need to be freed.</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span>  const char *pidf_element_str;</span><br><span style="color: hsl(0, 100%, 40%);">-   const char *method_str;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *note_well_str;</span><br><span style="color: hsl(0, 100%, 40%);">-      SCOPE_ENTER(3, "%s\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Attributes and element text however are allocated on the fly</span><br><span style="color: hsl(120, 100%, 40%);">+        * so they DO need to be freed after use.</span><br><span style="color: hsl(120, 100%, 40%);">+      */</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *id = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *format_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *method_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *note_well_str = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_xml_doc_dump_memory(result_doc, &doc_str, &doc_len);</span><br><span style="color: hsl(0, 100%, 40%);">-        ast_trace(5, "xslt result doc:\n%s\n", doc_str);</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_xml_free_text(doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+   SCOPE_ENTER(3, "%s\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!result_doc) {</span><br><span style="color: hsl(120, 100%, 40%);">+            SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: result_doc was NULL", ref_str);</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 (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               char *doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+         int doc_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_xml_doc_dump_memory(result_doc, &doc_str, &doc_len);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_trace(5, "xslt result doc len: %d\n%s\n", doc_len, doc_len ? doc_str : "<empty>");</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_xml_free_text(doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span> </span><br><span>        presence = ast_xml_get_root(result_doc);</span><br><span style="color: hsl(0, 100%, 40%);">-        pidf_element = ast_xml_node_get_children(presence);</span><br><span style="color: hsl(0, 100%, 40%);">-     location_info = ast_xml_find_child_element(pidf_element, "location-info", NULL, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-        usage_rules = ast_xml_find_child_element(pidf_element, "usage-rules", NULL, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-    method = ast_xml_find_child_element(pidf_element, "method", NULL, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-      note_well = ast_xml_find_child_element(pidf_element, "note-well", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!presence) {</span><br><span style="color: hsl(120, 100%, 40%);">+              SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Can't find 'presence' root element\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span style="color: hsl(0, 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%);">+  pidf_element = ast_xml_node_get_children(presence);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!pidf_element) {</span><br><span style="color: hsl(120, 100%, 40%);">+          SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Can't find a device, tuple or person element\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 ref_str);</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%);">+   id = ast_xml_get_attribute(pidf_element, "id");</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ast_strlen_zero(id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_xml_free_attr(id);</span><br><span style="color: hsl(120, 100%, 40%);">+                id = ast_xml_get_attribute(presence, "entity");</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 (ast_strlen_zero(id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            SCOPE_EXIT_RTN_VALUE(NULL, "%s: Unable to find 'id' attribute\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  eprofile = ast_geoloc_eprofile_alloc(id);</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_xml_free_attr(id);</span><br><span>       if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+           SCOPE_EXIT_RTN_VALUE(NULL, "%s: Allocation failure\n", ref_str);</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%);">+   location_info = ast_xml_find_child_element(pidf_element, "location-info", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!location_info) {</span><br><span style="color: hsl(120, 100%, 40%);">+         SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Can't find a location-info element\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   ref_str);</span><br><span>    }</span><br><span> </span><br><span>        format_str = ast_xml_get_attribute(location_info, "format");</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ast_strlen_zero(format_str)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            SCOPE_EXIT_RTN_VALUE(NULL, "%s: Unable to find 'format' attribute\n", ref_str);</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_NONE;</span><br><span>        if (strcasecmp(format_str, "gml") == 0) {</span><br><span>          eprofile->format = AST_GEOLOC_FORMAT_GML;</span><br><span>         } else if (strcasecmp(format_str, "civicAddress") == 0) {</span><br><span>          eprofile->format = AST_GEOLOC_FORMAT_CIVIC_ADDRESS;</span><br><span style="color: hsl(0, 100%, 40%);">-  } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                ao2_ref(eprofile, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-          SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unknown format '%s'\n", reference_string, format_str);</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   pidf_element_str = ast_xml_node_get_name(pidf_element);</span><br><span style="color: hsl(0, 100%, 40%);">- eprofile->pidf_element = geoloc_pidf_element_str_to_enum(pidf_element_str);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (eprofile->format == AST_GEOLOC_FORMAT_NONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+          char *dup_format_str = ast_strdupa(format_str);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_xml_free_attr(format_str);</span><br><span style="color: hsl(120, 100%, 40%);">+                ao2_ref(eprofile, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unknown format '%s'\n", ref_str, dup_format_str);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_xml_free_attr(format_str);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      eprofile->location_info = var_list_from_loc_info(location_info, eprofile->format, reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+    pidf_element_str = ast_xml_node_get_name(pidf_element);</span><br><span style="color: hsl(120, 100%, 40%);">+       eprofile->pidf_element = ast_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%);">+  eprofile->location_info = var_list_from_loc_info(location_info, eprofile->format, ref_str);</span><br><span>    if (!eprofile->location_info) {</span><br><span>           ao2_ref(eprofile, -1);</span><br><span>               SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">-                       "%s: Unable to create location variables\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+                     "%s: Unable to create location variables\n", ref_str);</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   eprofile->usage_rules = var_list_from_node(usage_rules, reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * The function calls that follow are all NULL tolerant</span><br><span style="color: hsl(120, 100%, 40%);">+        * so no need for explicit error checking.</span><br><span style="color: hsl(120, 100%, 40%);">+     */</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%);">+  eprofile->usage_rules = var_list_from_node(usage_rules, ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+  confidence = ast_xml_find_child_element(location_info, "confidence", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+   eprofile->confidence = var_list_from_confidence(confidence, ref_str);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  method = ast_xml_find_child_element(pidf_element, "method", NULL, NULL);</span><br><span>   method_str = ast_xml_get_text(method);</span><br><span>       ast_string_field_set(eprofile, method, method_str);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_xml_free_text(method_str);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    note_well = ast_xml_find_child_element(pidf_element, "note-well", NULL, NULL);</span><br><span>     note_well_str = ast_xml_get_text(note_well);</span><br><span>         ast_string_field_set(eprofile, notes, note_well_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_xml_free_text(note_well_str);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   SCOPE_EXIT_RTN_VALUE(eprofile, "%s: Done.\n", reference_string);</span><br><span style="color: hsl(120, 100%, 40%);">+    SCOPE_EXIT_RTN_VALUE(eprofile, "%s: Done.\n", ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int is_pidf_lo(struct ast_xml_doc *result_doc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_xml_node *presence;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_xml_node *pidf_element;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_xml_node *location_info;</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *pidf_element_name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!result_doc) {</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%);">+     presence = ast_xml_get_root(result_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!presence || !ast_strings_equal("presence", ast_xml_node_get_name(presence))) {</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%);">+   pidf_element = ast_xml_node_get_children(presence);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!pidf_element) {</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%);">+     pidf_element_name = ast_xml_node_get_name(pidf_element);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ast_strings_equal(pidf_element_name, "device") &&</span><br><span style="color: hsl(120, 100%, 40%);">+              !ast_strings_equal(pidf_element_name, "tuple") &&</span><br><span style="color: hsl(120, 100%, 40%);">+           !ast_strings_equal(pidf_element_name, "person")) {</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%);">+   location_info = ast_xml_find_child_element(pidf_element, "location-info", NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!location_info) {</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%);">+   return 1;</span><br><span> }</span><br><span> </span><br><span> struct ast_geoloc_eprofile *ast_geoloc_eprofile_create_from_pidf(</span><br><span>      struct ast_xml_doc *pidf_xmldoc, const char *geoloc_uri, const char *ref_str)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      RAII_VAR(struct ast_xml_doc *, result_doc, NULL, ast_xml_close);</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_geoloc_eprofile *eprofile;</span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * The namespace prefixes used here (dm, def, gp, etc) don't have to match</span><br><span style="color: hsl(0, 100%, 40%);">-   * the ones used in the received PIDF-LO document but they MUST match the</span><br><span style="color: hsl(0, 100%, 40%);">-        * ones in the embedded pidf_to_eprofile stylesheet.</span><br><span style="color: hsl(0, 100%, 40%);">-     *</span><br><span style="color: hsl(0, 100%, 40%);">-       * RFC5491 Rule 8 states that...</span><br><span style="color: hsl(0, 100%, 40%);">-         * Where a PIDF document contains more than one <geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-     * element, the priority of interpretation is given to the first</span><br><span style="color: hsl(0, 100%, 40%);">-     * <device> element in the document containing a location.  If no</span><br><span style="color: hsl(0, 100%, 40%);">-     * <device> element containing a location is present in the document,</span><br><span style="color: hsl(0, 100%, 40%);">-     * then priority is given to the first <tuple> element containing a</span><br><span style="color: hsl(0, 100%, 40%);">-     * location.  Locations contained in <person> tuples SHOULD only be</span><br><span style="color: hsl(0, 100%, 40%);">-     * used as a last resort.</span><br><span style="color: hsl(0, 100%, 40%);">-     *</span><br><span style="color: hsl(0, 100%, 40%);">-     * Reminder: xpath arrays are 1-based not 0-based.</span><br><span style="color: hsl(0, 100%, 40%);">-         */</span><br><span style="color: hsl(0, 100%, 40%);">-     const char *find_device[] = { "path", "/def:presence/dm:device[.//gp:location-info][1]", NULL};</span><br><span style="color: hsl(0, 100%, 40%);">-     const char *find_tuple[] = { "path", "/def:presence/def:tuple[.//gp:location-info][1]", NULL};</span><br><span style="color: hsl(0, 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%);">+   struct ast_xml_doc *result_doc = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_geoloc_eprofile *eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       SCOPE_ENTER(3, "%s\n", ref_str);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  result_doc = ast_xslt_apply(pidf_to_eprofile_xslt, pidf_xmldoc, find_device);</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!result_doc || !ast_xml_node_get_children((struct ast_xml_node *)result_doc)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_xml_close(result_doc);</span><br><span style="color: hsl(0, 100%, 40%);">-              result_doc = ast_xslt_apply(pidf_to_eprofile_xslt, pidf_xmldoc, find_tuple);</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!result_doc || !ast_xml_node_get_children((struct ast_xml_node *)result_doc)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_xml_close(result_doc);</span><br><span style="color: hsl(0, 100%, 40%);">-              result_doc = ast_xslt_apply(pidf_to_eprofile_xslt, pidf_xmldoc, find_person);</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 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%);">+   result_doc = ast_xslt_apply(pidf_to_eprofile_xslt, pidf_xmldoc, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!is_pidf_lo(result_doc)) {</span><br><span>               SCOPE_EXIT_RTN_VALUE(NULL, "%s: Not a PIDF-LO.  Skipping.\n", ref_str);</span><br><span>    }</span><br><span> </span><br><span>@@ -546,17 +695,27 @@</span><br><span>         *  </presence></span><br><span>         *</span><br><span>    * Regardless of whether the pidf-element was tuple, device or person and whether</span><br><span style="color: hsl(0, 100%, 40%);">-        * the format is gml or civicAddress, the presence, pidf-element, location-info,</span><br><span style="color: hsl(0, 100%, 40%);">-         * usage-rules and method elements should be there although usage-rules and method</span><br><span style="color: hsl(0, 100%, 40%);">-       * may be empty.</span><br><span style="color: hsl(120, 100%, 40%);">+       * the format is gml or civicAddress, the presence, pidf-element and location-info</span><br><span style="color: hsl(120, 100%, 40%);">+     * elements should be there.</span><br><span>          *</span><br><span style="color: hsl(0, 100%, 40%);">-       * The contents of the location-info and usage-rules elements can be passed directly to</span><br><span style="color: hsl(0, 100%, 40%);">-  * ast_variable_list_from_string().</span><br><span style="color: hsl(120, 100%, 40%);">+    * The confidence, usage-rules and note-well elements are optional.</span><br><span>   */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- eprofile = geoloc_eprofile_create_from_xslt_result(result_doc, ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               char *doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+         int doc_len = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    if (geoloc_uri) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_xml_doc_dump_memory(result_doc, &doc_str, &doc_len);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_trace(5, "Intermediate doc len: %d\n%s\n", doc_len, doc_len ? doc_str : "<empty>");</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_xml_free_text(doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+           doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+               doc_len = 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%);">+   eprofile = geoloc_eprofile_create_from_xslt_result(result_doc, ref_str);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_xml_close(result_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (eprofile && geoloc_uri) {</span><br><span>                set_loc_src(eprofile, geoloc_uri, ref_str);</span><br><span>  }</span><br><span> </span><br><span>@@ -586,6 +745,7 @@</span><br><span>  RAII_VAR(struct ast_xml_node *, pidf_node, NULL, ast_xml_free_node);</span><br><span>         struct ast_xml_node *rtn_pidf_node;</span><br><span>  struct ast_xml_node *loc_node;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_xml_node *confidence_node;</span><br><span>        struct ast_xml_node *info_node;</span><br><span>      struct ast_xml_node *rules_node;</span><br><span>     struct ast_xml_node *method_node;</span><br><span>@@ -613,7 +773,7 @@</span><br><span>              SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'location-info' XML node\n",</span><br><span>                       ref_string);</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       rc = ast_xml_set_attribute(loc_node, "format", geoloc_format_to_name(eprofile->format));</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = ast_xml_set_attribute(loc_node, "format", ast_geoloc_format_to_name(eprofile->format));</span><br><span>    if (rc != 0) {</span><br><span>               SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to set 'format' XML attribute\n", ref_string);</span><br><span>       }</span><br><span>@@ -625,14 +785,33 @@</span><br><span>    } else {</span><br><span>             info_node = geoloc_gml_list_to_xml(resolved_location, ref_string);</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_variables_destroy(resolved_location);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (!info_node) {</span><br><span>            SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create XML from '%s' list\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                        ref_string, geoloc_format_to_name(eprofile->format));</span><br><span style="color: hsl(120, 100%, 40%);">+                      ref_string, ast_geoloc_format_to_name(eprofile->format));</span><br><span>         }</span><br><span>    if (!ast_xml_add_child(loc_node, info_node)) {</span><br><span>               ast_xml_free_node(info_node);</span><br><span>                SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable add '%s' node to XML document\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                       ref_string, geoloc_format_to_name(eprofile->format));</span><br><span style="color: hsl(120, 100%, 40%);">+                      ref_string, ast_geoloc_format_to_name(eprofile->format));</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 (eprofile->confidence) {</span><br><span style="color: hsl(120, 100%, 40%);">+                const char *value = S_OR(ast_variable_find_in_list(eprofile->confidence, "value"), "95");</span><br><span style="color: hsl(120, 100%, 40%);">+              const char *pdf = S_OR(ast_variable_find_in_list(eprofile->confidence, "pdf"), "unknown");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           confidence_node = ast_xml_new_child(loc_node, "confidence");</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!confidence_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create 'confidence' XML node\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             rc = ast_xml_set_attribute(confidence_node, "pdf", pdf);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to set 'pdf' attribute on 'confidence' element\n", ref_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%);">+           ast_xml_set_text(confidence_node, value);</span><br><span>    }</span><br><span> </span><br><span>        rules_node = ast_xml_new_child(pidf_node, "usage-rules");</span><br><span>@@ -646,6 +825,7 @@</span><br><span>            struct ast_xml_node *ur = ast_xml_new_child(rules_node, var->name);</span><br><span>               ast_xml_set_text(ur, var->value);</span><br><span>         }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_variables_destroy(resolved_usage);</span><br><span> </span><br><span>   if (!ast_strlen_zero(eprofile->method)) {</span><br><span>                 method_node = ast_xml_new_child(pidf_node, "method");</span><br><span>@@ -699,8 +879,8 @@</span><br><span>        struct ast_geoloc_eprofile *eprofile;</span><br><span>        int eprofile_count = 0;</span><br><span>      int i;</span><br><span style="color: hsl(0, 100%, 40%);">-  RAII_VAR(char *, doc_str, NULL, ast_xml_free_text);</span><br><span style="color: hsl(0, 100%, 40%);">-     int doc_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ int doc_len = 0;</span><br><span>     int rc = 0;</span><br><span>  SCOPE_ENTER(3, "%s\n", ref_string);</span><br><span> </span><br><span>@@ -726,20 +906,28 @@</span><br><span>            struct ast_xml_node *new_loc = NULL;</span><br><span>                 struct ast_xml_node *new_loc_child = NULL;</span><br><span>           struct ast_xml_node *new_loc_child_dup = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                const char *entity = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+            int has_no_entity = 0;</span><br><span>               eprofile = ast_geoloc_datastore_get_eprofile(ds, i);</span><br><span>                 if (eprofile->format == AST_GEOLOC_FORMAT_URI) {</span><br><span>                  continue;</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (ast_strlen_zero(ast_xml_get_attribute(root_node, "entity"))) {</span><br><span style="color: hsl(120, 100%, 40%);">+          entity = ast_xml_get_attribute(root_node, "entity");</span><br><span style="color: hsl(120, 100%, 40%);">+                has_no_entity = ast_strlen_zero(entity);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_xml_free_attr(entity);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (has_no_entity) {</span><br><span>                         rc = ast_xml_set_attribute(root_node, "entity", eprofile->id);</span><br><span>                  if (rc != 0) {</span><br><span>                               SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to set 'entity' XML attribute\n", ref_string);</span><br><span>                       }</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           temp_node = geoloc_eprofile_to_intermediate(geoloc_pidf_element_to_name(eprofile->pidf_element),</span><br><span style="color: hsl(120, 100%, 40%);">+           temp_node = geoloc_eprofile_to_intermediate(ast_geoloc_pidf_element_to_name(eprofile->pidf_element),</span><br><span>                      eprofile, chan, ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!temp_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create temp_node\n", ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span> </span><br><span>                if (!pidfs[eprofile->pidf_element]) {</span><br><span>                     pidfs[eprofile->pidf_element] = temp_node;</span><br><span>@@ -756,18 +944,18 @@</span><br><span>                ast_xml_free_node(temp_node);</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_xml_doc_dump_memory(intermediate, &doc_str, &doc_len);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (doc_len == 0 || !doc_str) {</span><br><span style="color: hsl(0, 100%, 40%);">-         SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to dump intermediate doc to string\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_xml_doc_dump_memory(intermediate, &doc_str, &doc_len);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_trace(5, "Intermediate doc len: %d\n%s\n", doc_len, doc_len ? doc_str : "<empty>");</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_xml_free_text(doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+           doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+               doc_len = 0;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_trace(5, "Intermediate doc:\n%s\n", doc_str);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>  pidf_doc = ast_xslt_apply(eprofile_to_pidf_xslt, intermediate, NULL);</span><br><span>        if (!pidf_doc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create final PIDF-LO doc from intermediate doc:\n%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      ref_string, doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+         SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create final PIDF-LO doc from intermediate docs\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        ref_string);</span><br><span>         }</span><br><span> </span><br><span>        ast_xml_doc_dump_memory(pidf_doc, &doc_str, &doc_len);</span><br><span>@@ -777,6 +965,93 @@</span><br><span>        }</span><br><span> </span><br><span>        rc = ast_str_set(buf, 0, "%s", doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_xml_free_text(doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to extend buffer (%d)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                     ref_string, 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%);">+   ast_trace(5, "Final doc:\n%s\n", ast_str_buffer(*buf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   SCOPE_EXIT_RTN_VALUE(ast_str_buffer(*buf), "%s: Done\n", ref_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%);">+const char *ast_geoloc_eprofile_to_pidf(struct ast_geoloc_eprofile *eprofile,</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_channel *chan, struct ast_str **buf, const char * ref_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 *, intermediate, NULL, ast_xml_close);</span><br><span style="color: hsl(120, 100%, 40%);">+    RAII_VAR(struct ast_xml_doc *, pidf_doc, NULL, ast_xml_close);</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_xml_node *root_node;</span><br><span style="color: hsl(120, 100%, 40%);">+       char *doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ int doc_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_xml_node *temp_node = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *entity = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    int has_no_entity = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      SCOPE_ENTER(3, "%s\n", ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!eprofile || !chan || !buf || !*buf || ast_strlen_zero(ref_string)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SCOPE_EXIT_RTN_VALUE(NULL, "%s: One of eprofile, chan or buf was NULL\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   ref_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%);">+   if (eprofile->format == AST_GEOLOC_FORMAT_URI) {</span><br><span style="color: hsl(120, 100%, 40%);">+           SCOPE_EXIT_RTN_VALUE(NULL, "%s: eprofile '%s' was a URI format\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                  ref_string, eprofile->id);</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%);">+   intermediate = ast_xml_new();</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!intermediate) {</span><br><span style="color: hsl(120, 100%, 40%);">+          SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create XML document\n", ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     root_node = ast_xml_new_node("presence");</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!root_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create root XML node\n", ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_xml_set_root(intermediate, root_node);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  entity = ast_xml_get_attribute(root_node, "entity");</span><br><span style="color: hsl(120, 100%, 40%);">+        has_no_entity = ast_strlen_zero(entity);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_xml_free_attr(entity);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (has_no_entity) {</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = ast_xml_set_attribute(root_node, "entity", eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to set 'entity' XML attribute\n", ref_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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   temp_node = geoloc_eprofile_to_intermediate(</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_geoloc_pidf_element_to_name(eprofile->pidf_element), eprofile, chan, ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!temp_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create temp_node for eprofile '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                     ref_string, eprofile->id);</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_xml_add_child(root_node, temp_node);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (TRACE_ATLEAST(5)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_xml_doc_dump_memory(intermediate, &doc_str, &doc_len);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_trace(5, "Intermediate doc len: %d\n%s\n", doc_len, doc_len ? doc_str : "<empty>");</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_xml_free_text(doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+           doc_str = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+               doc_len = 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%);">+   pidf_doc = ast_xslt_apply(eprofile_to_pidf_xslt, intermediate, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!pidf_doc) {</span><br><span style="color: hsl(120, 100%, 40%);">+              SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create final PIDF-LO doc from intermediate doc\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 ref_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%);">+   ast_xml_doc_dump_memory(pidf_doc, &doc_str, &doc_len);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (doc_len == 0 || !doc_str) {</span><br><span style="color: hsl(120, 100%, 40%);">+               SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to dump final PIDF-LO doc to string\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       ref_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%);">+   rc = ast_str_set(buf, 0, "%s", doc_str);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_xml_free_text(doc_str);</span><br><span>  if (rc <= 0) {</span><br><span>            SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to extend buffer (%d)\n",</span><br><span>                    ref_string, rc);</span><br><span>@@ -899,10 +1174,9 @@</span><br><span>     RAII_VAR(struct ast_str *, str, NULL, ast_free);</span><br><span>     RAII_VAR(struct ast_geoloc_eprofile *, eprofile,  NULL, ao2_cleanup);</span><br><span>        RAII_VAR(struct ast_xml_doc *, result_doc, NULL, ast_xml_close);</span><br><span style="color: hsl(0, 100%, 40%);">-        const char *search[] = { "path", path, NULL };</span><br><span> </span><br><span>         if (!ast_strlen_zero(path)) {</span><br><span style="color: hsl(0, 100%, 40%);">-           result_doc = ast_xslt_apply(pidf_to_eprofile_xslt, pidf_xmldoc, (const char **)search);</span><br><span style="color: hsl(120, 100%, 40%);">+               result_doc = ast_xslt_apply(pidf_to_eprofile_xslt, pidf_xmldoc, NULL);</span><br><span>               ast_test_validate(test, (result_doc && ast_xml_node_get_children((struct ast_xml_node *)result_doc)));</span><br><span> </span><br><span>           eprofile = geoloc_eprofile_create_from_xslt_result(result_doc, "test_create_from_xslt");</span><br><span>@@ -912,8 +1186,8 @@</span><br><span> </span><br><span>        ast_test_validate(test, eprofile != NULL);</span><br><span>   ast_test_status_update(test, "ID: '%s'  pidf_element: '%s'  format: '%s'  method: '%s'\n", eprofile->id,</span><br><span style="color: hsl(0, 100%, 40%);">-           geoloc_pidf_element_to_name(eprofile->pidf_element),</span><br><span style="color: hsl(0, 100%, 40%);">-         geoloc_format_to_name(eprofile->format),</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_geoloc_pidf_element_to_name(eprofile->pidf_element),</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_geoloc_format_to_name(eprofile->format),</span><br><span>              eprofile->method);</span><br><span> </span><br><span>    ast_test_validate(test, ast_strings_equal(eprofile->id, id));</span><br><span>@@ -959,34 +1233,15 @@</span><br><span> </span><br><span>        res = validate_eprofile(test, pidf_xmldoc,</span><br><span>           NULL,</span><br><span style="color: hsl(0, 100%, 40%);">-           "arcband-2d",</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_PIDF_ELEMENT_DEVICE,</span><br><span style="color: hsl(120, 100%, 40%);">+              "point-2d",</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_PIDF_ELEMENT_TUPLE,</span><br><span>              AST_GEOLOC_FORMAT_GML,</span><br><span style="color: hsl(0, 100%, 40%);">-          "TA-NMR",</span><br><span style="color: hsl(0, 100%, 40%);">-             "shape=ArcBand,crs=2d,pos=-43.5723 153.21760,innerRadius=3594,"</span><br><span style="color: hsl(0, 100%, 40%);">-                               "outerRadius=4148,startAngle=20 radians,openingAngle=20 radians",</span><br><span style="color: hsl(0, 100%, 40%);">-             "retransmission-allowed='yes',ruleset-preference='https:/www/more.com',"</span><br><span style="color: hsl(0, 100%, 40%);">-                      "retention-expires='2007-06-22T20:57:29Z'"</span><br><span style="color: hsl(120, 100%, 40%);">+          "Manual",</span><br><span style="color: hsl(120, 100%, 40%);">+           "shape=Point,crs=2d,pos=-34.410649 150.87651",</span><br><span style="color: hsl(120, 100%, 40%);">+              "retransmission-allowed='no',retention-expiry='2010-11-14T20:00:00Z'"</span><br><span>              );</span><br><span>   ast_test_validate(test, res == AST_TEST_PASS);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      res = validate_eprofile(test, pidf_xmldoc,</span><br><span style="color: hsl(0, 100%, 40%);">-              "/def:presence/dm:device[.//ca:civicAddress][1]",</span><br><span style="color: hsl(0, 100%, 40%);">-             "pres:alice@asterisk.org",</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_PIDF_ELEMENT_DEVICE,</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_GEOLOC_FORMAT_CIVIC_ADDRESS,</span><br><span style="color: hsl(0, 100%, 40%);">-                "GPS",</span><br><span style="color: hsl(0, 100%, 40%);">-                "lang=en-AU,country=AU,A1=NSW,A3=Wollongong,A4=North Wollongong,"</span><br><span style="color: hsl(0, 100%, 40%);">-                     "RD=Flinders,STS=Street,RDBR=Campbell Street,LMK=Gilligan's Island,"</span><br><span style="color: hsl(0, 100%, 40%);">-                      "LOC=Corner,NAM=Video Rental Store,PC=2500,ROOM=Westerns and Classics,"</span><br><span style="color: hsl(0, 100%, 40%);">-                       "PLC=store,POBOX=Private Box 15",</span><br><span style="color: hsl(0, 100%, 40%);">-             "retransmission-allowed='yes',ruleset-preference='https:/www/more.com',"</span><br><span style="color: hsl(0, 100%, 40%);">-                      "retention-expires='2007-06-22T20:57:29Z'"</span><br><span style="color: hsl(0, 100%, 40%);">-            );</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_test_validate(test, res == AST_TEST_PASS);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>       return res;</span><br><span> }</span><br><span> </span><br><span>diff --git a/res/res_geolocation/geoloc_gml.c b/res/res_geolocation/geoloc_gml.c</span><br><span>index 8a66162..9a5942c 100644</span><br><span>--- a/res/res_geolocation/geoloc_gml.c</span><br><span>+++ b/res/res_geolocation/geoloc_gml.c</span><br><span>@@ -247,6 +247,11 @@</span><br><span> </span><br><span>         SCOPE_ENTER(3, "%s", ref_string);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       if (!resolved_location) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: resolved_location was NULL\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       ref_string);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  shape = ast_variable_find_in_list(resolved_location, "shape");</span><br><span>     if (ast_strlen_zero(shape)) {</span><br><span>                SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: There's no 'shape' parameter\n",</span><br><span>diff --git a/res/res_geolocation/geoloc_private.h b/res/res_geolocation/geoloc_private.h</span><br><span>index 860f3b5..6b9a63e 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,18 +25,8 @@</span><br><span> #include "asterisk/lock.h"</span><br><span> #include "asterisk/res_geolocation.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define CONFIG_STR_TO_ENUM_DECL(_stem) int geoloc_ ## _stem ## _str_to_enum(const char *str);</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_STR_TO_ENUM_DECL(pidf_element)</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_STR_TO_ENUM_DECL(format);</span><br><span style="color: hsl(0, 100%, 40%);">-CONFIG_STR_TO_ENUM_DECL(action);</span><br><span style="color: hsl(0, 100%, 40%);">-#define GEOLOC_ENUM_TO_NAME_DECL(_stem) const char * geoloc_ ## _stem ## _to_name(int ix);</span><br><span style="color: hsl(0, 100%, 40%);">-GEOLOC_ENUM_TO_NAME_DECL(pidf_element)</span><br><span style="color: hsl(0, 100%, 40%);">-GEOLOC_ENUM_TO_NAME_DECL(format);</span><br><span style="color: hsl(0, 100%, 40%);">-GEOLOC_ENUM_TO_NAME_DECL(action);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #define CONFIG_STR_TO_ENUM(_stem) \</span><br><span style="color: hsl(0, 100%, 40%);">-int geoloc_ ## _stem ## _str_to_enum(const char *str) \</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_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>@@ -51,7 +41,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 = geoloc_ ## _stem ## _str_to_enum(var->value); \</span><br><span style="color: hsl(120, 100%, 40%);">+      int enumval = ast_geoloc_ ## _stem ## _str_to_enum(var->value); \</span><br><span>         if (enumval == -1) { \</span><br><span>               return -1; \</span><br><span>         } \</span><br><span>@@ -61,7 +51,7 @@</span><br><span> </span><br><span> </span><br><span> #define GEOLOC_ENUM_TO_NAME(_stem) \</span><br><span style="color: hsl(0, 100%, 40%);">-const char * geoloc_ ## _stem ## _to_name(int ix) \</span><br><span style="color: hsl(120, 100%, 40%);">+const char * ast_geoloc_ ## _stem ## _to_name(int ix) \</span><br><span> { \</span><br><span>   if (!ARRAY_IN_BOUNDS(ix, _stem ## _names)) { \</span><br><span>               return "none"; \</span><br><span>diff --git a/res/res_geolocation/pidf_lo_test.xml b/res/res_geolocation/pidf_lo_test.xml</span><br><span>index 3948063..bea98d6 100644</span><br><span>--- a/res/res_geolocation/pidf_lo_test.xml</span><br><span>+++ b/res/res_geolocation/pidf_lo_test.xml</span><br><span>@@ -6,6 +6,7 @@</span><br><span>    xmlns:gbp="urn:ietf:params:xml:ns:pidf:geopriv10:basicPolicy"</span><br><span>      xmlns:gml="http://www.opengis.net/gml"</span><br><span>     xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"</span><br><span style="color: hsl(120, 100%, 40%);">+    xmlns:con="urn:ietf:params:xml:ns:geopriv:conf"</span><br><span>    xmlns:gs="http://www.opengis.net/pidflo/1.0"></span><br><span>   <tuple id="point-2d"></span><br><span>                <status></span><br><span>@@ -14,299 +15,19 @@</span><br><span>                                        <gml:Point srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span>                                             <gml:pos>-34.410649 150.87651</gml:pos></span><br><span>                                  </gml:Point></span><br><span style="color: hsl(120, 100%, 40%);">+                            <con:confidence pdf="normal">66</con:confidence></span><br><span>                               </gp:location-info></span><br><span>                            <gp:usage-rules></span><br><span>                                       <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span>                                      <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span>                                </gp:usage-rules></span><br><span>                              <gp:method>Manual</gp:method></span><br><span style="color: hsl(120, 100%, 40%);">+                             <gp:note-well></span><br><span style="color: hsl(120, 100%, 40%);">+                                  this is a test</span><br><span style="color: hsl(120, 100%, 40%);">+                                        of the emergency broadcast system</span><br><span style="color: hsl(120, 100%, 40%);">+                             </gp:note-well></span><br><span>                        </gp:geopriv></span><br><span>          </status></span><br><span>              <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span>      </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <dm:person id="point-3d"></span><br><span style="color: hsl(0, 100%, 40%);">-               <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                      <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                <gml:Point srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gml:pos>-34.410649 150.87651 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                </gml:Point></span><br><span style="color: hsl(0, 100%, 40%);">-                      </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                       <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                   </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                 <gp:method>802.11</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-               </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             <dm:timestamp>2007-06-24T12:28:04Z</dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-   </dm:person></span><br><span style="color: hsl(0, 100%, 40%);">-      <tuple id="circle-2d"></span><br><span style="color: hsl(0, 100%, 40%);">-          <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:Circle srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gml:pos>-34.410649 150.87651</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                             <gs:radius uom="urn:ogc:def:uom:EPSG::9001">30</gs:radius></span><br><span style="color: hsl(0, 100%, 40%);">-                                        </gs:Circle></span><br><span style="color: hsl(0, 100%, 40%);">-                              </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>802.11</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                       </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <tuple id="circle-3d"></span><br><span style="color: hsl(0, 100%, 40%);">-          <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:Circle srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gml:pos>-34.410649 150.87651 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gs:radius uom="urn:ogc:def:uom:EPSG::9001">30</gs:radius></span><br><span style="color: hsl(0, 100%, 40%);">-                                        </gs:Circle></span><br><span style="color: hsl(0, 100%, 40%);">-                              </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>802.11</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                       </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <dm:person id="polygon-2d"></span><br><span style="color: hsl(0, 100%, 40%);">-             <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                      <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                            <gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                                  <gml:pos>43.311 -73.422</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   <gml:pos>43.111 -73.322</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   <gml:pos>43.111 -73.222</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   <gml:pos>43.311 -73.122</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   <gml:pos>43.411 -73.222</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   <gml:pos>43.411 -73.322</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   <gml:pos>43.311 -73.422</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                           </gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                 </gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gml:Polygon></span><br><span style="color: hsl(0, 100%, 40%);">-                    </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                       <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                   </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                 <gp:method>802.11</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-               </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             <dm:timestamp>2007-06-24T12:28:04Z</dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-   </dm:person></span><br><span style="color: hsl(0, 100%, 40%);">-      <dm:person id="polygon-3d"></span><br><span style="color: hsl(0, 100%, 40%);">-             <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                      <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                            <gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                                  <gml:pos>43.311 -73.422 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                      <gml:pos>43.111 -73.322 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                      <gml:pos>43.111 -73.222 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                      <gml:pos>43.311 -73.122 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                      <gml:pos>43.411 -73.222 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                      <gml:pos>43.411 -73.322 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                                      <gml:pos>43.311 -73.422 1800</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                              </gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                 </gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gml:Polygon></span><br><span style="color: hsl(0, 100%, 40%);">-                    </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                       <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                   </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                 <gp:method>802.11</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-               </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             <dm:timestamp>2007-06-24T12:28:04Z</dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-   </dm:person></span><br><span style="color: hsl(0, 100%, 40%);">-      <tuple id="polygon-poslist-2d"></span><br><span style="color: hsl(0, 100%, 40%);">-         <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(0, 100%, 40%);">-                                              <gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                                    <gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                                          <gml:posList></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                     43.311 -73.422 43.111 -73.322</span><br><span style="color: hsl(0, 100%, 40%);">-                                                                   43.111 -73.222 43.311 -73.122</span><br><span style="color: hsl(0, 100%, 40%);">-                                                                   43.411 -73.222 43.411 -73.322</span><br><span style="color: hsl(0, 100%, 40%);">-                                                                   43.311 -73.422</span><br><span style="color: hsl(0, 100%, 40%);">-                                                          </gml:posList></span><br><span style="color: hsl(0, 100%, 40%);">-                                                    </gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                         </gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                   </gml:Polygon></span><br><span style="color: hsl(0, 100%, 40%);">-                            </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>Wiremap</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                      </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <tuple id="polygon-poslist-3d"></span><br><span style="color: hsl(0, 100%, 40%);">-         <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gml:Polygon srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                              <gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                                    <gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                                          <gml:posList></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                     43.311 -73.422 1800 43.111 -73.322 1800</span><br><span style="color: hsl(0, 100%, 40%);">-                                                                 43.111 -73.222 1800 43.311 -73.122 1800</span><br><span style="color: hsl(0, 100%, 40%);">-                                                                 43.411 -73.222 1800 43.411 -73.322 1800</span><br><span style="color: hsl(0, 100%, 40%);">-                                                                 43.311 -73.422 1800</span><br><span style="color: hsl(0, 100%, 40%);">-                                                             </gml:posList></span><br><span style="color: hsl(0, 100%, 40%);">-                                                    </gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                         </gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                   </gml:Polygon></span><br><span style="color: hsl(0, 100%, 40%);">-                            </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>Wiremap</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                      </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <tuple id="ellipse-2d"></span><br><span style="color: hsl(0, 100%, 40%);">-         <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:Ellipse srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(0, 100%, 40%);">-                                               <gml:pos>42.5463 -73.2512</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                         <gs:semiMajorAxis uom="urn:ogc:def:uom:EPSG::9001">1275</gs:semiMajorAxis></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gs:semiMinorAxis uom="urn:ogc:def:uom:EPSG::9001">670</gs:semiMinorAxis></span><br><span style="color: hsl(0, 100%, 40%);">-                                         <gs:orientation uom="urn:ogc:def:uom:EPSG::9102">43.2</gs:orientation></span><br><span style="color: hsl(0, 100%, 40%);">-                                    </gs:Ellipse></span><br><span style="color: hsl(0, 100%, 40%);">-                             </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules/></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>Device-Assisted_A-GPS</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                        </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <dm:device id="arcband-2d"></span><br><span style="color: hsl(0, 100%, 40%);">-             <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                      <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                <gs:ArcBand srsName="urn:ogc:def:crs:EPSG::4326"></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <gml:pos>-43.5723 153.21760</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <gs:innerRadius uom="urn:ogc:def:uom:EPSG::9001">3594</gs:innerRadius></span><br><span style="color: hsl(0, 100%, 40%);">-                                    <gs:outerRadius uom="urn:ogc:def:uom:EPSG::9001">4148</gs:outerRadius></span><br><span style="color: hsl(0, 100%, 40%);">-                                    <gs:startAngle uom="urn:ogc:def:uom:EPSG::9102">20</gs:startAngle></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:openingAngle uom="urn:ogc:def:uom:EPSG::9102">20</gs:openingAngle></span><br><span style="color: hsl(0, 100%, 40%);">-                            </gs:ArcBand></span><br><span style="color: hsl(0, 100%, 40%);">-                     </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                       <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gp:retransmission-allowed>yes</gp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gp:ruleset-preference>https:/www/more.com</gp:ruleset-preference></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gp:retention-expires>2007-06-22T20:57:29Z</gp:retention-expires></span><br><span style="color: hsl(0, 100%, 40%);">-                   </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                 <gp:method>TA-NMR</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-               </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             <dm:deviceID>mac:1234567890ab</dm:deviceID></span><br><span style="color: hsl(0, 100%, 40%);">-         <dm:timestamp>2007-06-22T20:57:29Z</dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-   </dm:device></span><br><span style="color: hsl(0, 100%, 40%);">-      <tuple id="sphere"></span><br><span style="color: hsl(0, 100%, 40%);">-             <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:Sphere srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gml:pos>42.5463 -73.2512 26.3</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                            <gs:radius uom="urn:ogc:def:uom:EPSG::9001">850.24</gs:radius></span><br><span style="color: hsl(0, 100%, 40%);">-                                    </gs:Sphere></span><br><span style="color: hsl(0, 100%, 40%);">-                              </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <gbp:retransmission-allowed>no</gbp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <gbp:retention-expiry>2010-11-14T20:00:00Z</gbp:retention-expiry></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>Device-Based_A-GPS</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                   </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <tuple id="ellipsoid"></span><br><span style="color: hsl(0, 100%, 40%);">-          <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:Ellipsoid srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                             <gml:pos>42.5463 -73.2512 26.3</gml:pos></span><br><span style="color: hsl(0, 100%, 40%);">-                                            <gs:semiMajorAxis uom="urn:ogc:def:uom:EPSG::9001">7.7156</gs:semiMajorAxis></span><br><span style="color: hsl(0, 100%, 40%);">-                                              <gs:semiMinorAxis uom="urn:ogc:def:uom:EPSG::9001">3.31</gs:semiMinorAxis></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gs:verticalAxis uom="urn:ogc:def:uom:EPSG::9001">28.7</gs:verticalAxis></span><br><span style="color: hsl(0, 100%, 40%);">-                                          <gs:orientation uom="urn:ogc:def:uom:EPSG::9102">90</gs:orientation></span><br><span style="color: hsl(0, 100%, 40%);">-                                      </gs:Ellipsoid></span><br><span style="color: hsl(0, 100%, 40%);">-                           </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules/></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>Hybrid_A-GPS</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                 </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <tuple id="prism"></span><br><span style="color: hsl(0, 100%, 40%);">-              <status></span><br><span style="color: hsl(0, 100%, 40%);">-                  <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                              <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <gs:Prism srsName="urn:ogc:def:crs:EPSG::4979"></span><br><span style="color: hsl(0, 100%, 40%);">-                                         <gs:base></span><br><span style="color: hsl(0, 100%, 40%);">-                                                 <gml:Polygon></span><br><span style="color: hsl(0, 100%, 40%);">-                                                             <gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                    <gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                          <gml:posList></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                                     42.556844 -73.248157 36.6 <!--A --></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                                       42.656844 -73.248157 36.6 <!--B --></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                                       42.656844 -73.348157 36.6 <!--C --></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                                       42.556844 -73.348157 36.6 <!--D --></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                                       42.556844 -73.248157 36.6 <!--A --></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                               </gml:posList></span><br><span style="color: hsl(0, 100%, 40%);">-                                                                    </gml:LinearRing></span><br><span style="color: hsl(0, 100%, 40%);">-                                                         </gml:exterior></span><br><span style="color: hsl(0, 100%, 40%);">-                                                   </gml:Polygon></span><br><span style="color: hsl(0, 100%, 40%);">-                                            </gs:base></span><br><span style="color: hsl(0, 100%, 40%);">-                                                <gs:height uom="urn:ogc:def:uom:EPSG::9001">2.4</gs:height></span><br><span style="color: hsl(0, 100%, 40%);">-                                       </gs:Prism></span><br><span style="color: hsl(0, 100%, 40%);">-                               </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                               <gp:usage-rules/></span><br><span style="color: hsl(0, 100%, 40%);">-                         <gp:method>Wiremap</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-                      </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             </status></span><br><span style="color: hsl(0, 100%, 40%);">-         <timestamp>2007-06-22T20:57:29Z</timestamp></span><br><span style="color: hsl(0, 100%, 40%);">- </tuple></span><br><span style="color: hsl(0, 100%, 40%);">-  <dm:device></span><br><span style="color: hsl(0, 100%, 40%);">-               <gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-                      <gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                                <ca:civicAddress xml:lang="en-AU"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <ca:country>AU</ca:country></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <ca:A1>NSW</ca:A1></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <ca:A3>Wollongong</ca:A3></span><br><span style="color: hsl(0, 100%, 40%);">-                                   <ca:A4>North Wollongong</ca:A4></span><br><span style="color: hsl(0, 100%, 40%);">-                                     <ca:RD>Flinders</ca:RD></span><br><span style="color: hsl(0, 100%, 40%);">-                                     <ca:STS>Street</ca:STS></span><br><span style="color: hsl(0, 100%, 40%);">-                                     <ca:RDBR>Campbell Street</ca:RDBR></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <ca:LMK>Gilligan's Island</ca:LMK></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <ca:LOC>Corner</ca:LOC></span><br><span style="color: hsl(0, 100%, 40%);">-                                     <ca:NAM> Video Rental Store </ca:NAM></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <ca:PC>2500</ca:PC></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <ca:ROOM> Westerns and Classics </ca:ROOM></span><br><span style="color: hsl(0, 100%, 40%);">-                                  <ca:PLC>store</ca:PLC></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <ca:POBOX>Private Box 15</ca:POBOX></span><br><span style="color: hsl(0, 100%, 40%);">-                         </ca:civicAddress></span><br><span style="color: hsl(0, 100%, 40%);">-                        </gp:location-info></span><br><span style="color: hsl(0, 100%, 40%);">-                       <gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gp:retransmission-allowed>yes</gp:retransmission-allowed></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gp:ruleset-preference>https:/www/more.com</gp:ruleset-preference></span><br><span style="color: hsl(0, 100%, 40%);">-                          <gp:retention-expires>2007-06-22T20:57:29Z</gp:retention-expires></span><br><span style="color: hsl(0, 100%, 40%);">-                   </gp:usage-rules></span><br><span style="color: hsl(0, 100%, 40%);">-                 <gp:method>GPS</gp:method></span><br><span style="color: hsl(0, 100%, 40%);">-          </gp:geopriv></span><br><span style="color: hsl(0, 100%, 40%);">-             <dm:deviceID>mac:1234567890ab</dm:deviceID></span><br><span style="color: hsl(0, 100%, 40%);">-         <dm:timestamp>2007-06-22T20:57:29Z</dm:timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-   </dm:device></span><br><span> </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>index 05f4df8..95f000c 100644</span><br><span>--- a/res/res_geolocation/pidf_to_eprofile.xslt</span><br><span>+++ b/res/res_geolocation/pidf_to_eprofile.xslt</span><br><span>@@ -8,6 +8,7 @@</span><br><span>   xmlns:gml="http://www.opengis.net/gml"</span><br><span>     xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"</span><br><span>   xmlns:gs="http://www.opengis.net/pidflo/1.0"</span><br><span style="color: hsl(120, 100%, 40%);">+        xmlns:con="urn:ietf:params:xml:ns:geopriv:conf"</span><br><span>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"></span><br><span> </span><br><span> </span><br><span>@@ -41,34 +42,47 @@</span><br><span> </span><br><span>     <xsl:output method="xml" indent="yes"/></span><br><span>    <xsl:strip-space elements="*"/></span><br><span style="color: hsl(0, 100%, 40%);">- <xsl:param name="path"/></span><br><span> </span><br><span>         <!--</span><br><span>              Even though the "presence", "tuple", and "status" elements won't have namespaces in the</span><br><span>            incoming PIDF document, we have to use the pseudo-namespace "def" here because of namespace</span><br><span style="color: hsl(0, 100%, 40%);">-           processing quirks in libxml2 and libxslt.</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               We don't use namespace prefixes in the output document at all.</span><br><span style="color: hsl(120, 100%, 40%);">+            processing quirks in libxml2 and libxslt.  We don't use namespace prefixes in the output</span><br><span style="color: hsl(120, 100%, 40%);">+          document at all.</span><br><span>     --></span><br><span>       <xsl:template match="/def:presence"></span><br><span>                 <xsl:element name="presence"></span><br><span>                        <xsl:attribute name="entity"><xsl:value-of select="@entity"/></xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select="$path"/></span><br><span style="color: hsl(120, 100%, 40%);">+                 <!--</span><br><span style="color: hsl(120, 100%, 40%);">+                               We only want devices, tuples and persons (in that order) that</span><br><span style="color: hsl(120, 100%, 40%);">+                         have location-info elements.</span><br><span style="color: hsl(120, 100%, 40%);">+                   --></span><br><span style="color: hsl(120, 100%, 40%);">+                       <xsl:apply-templates select="dm:device[./gp:geopriv/gp:location-info]"/></span><br><span style="color: hsl(120, 100%, 40%);">+                      <xsl:apply-templates select="def:tuple[./def:status/gp:geopriv/gp:location-info]"/></span><br><span style="color: hsl(120, 100%, 40%);">+                   <xsl:apply-templates select="dm:person[.//gp:geopriv/gp:location-info]"/></span><br><span>            </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="dm:device"></span><br><span style="color: hsl(0, 100%, 40%);">-                <xsl:element name="device"></span><br><span style="color: hsl(120, 100%, 40%);">+   <xsl:template name="geopriv"></span><br><span style="color: hsl(120, 100%, 40%);">+                 <xsl:apply-templates select=".//gp:geopriv/gp:location-info"/></span><br><span style="color: hsl(120, 100%, 40%);">+                        <xsl:apply-templates select=".//gp:geopriv/gp:usage-rules"/></span><br><span style="color: hsl(120, 100%, 40%);">+                  <xsl:apply-templates select=".//gp:geopriv/gp:method"/></span><br><span style="color: hsl(120, 100%, 40%);">+                       <xsl:apply-templates select=".//gp:geopriv/gp:note-well"/></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="def:tuple"></span><br><span style="color: hsl(120, 100%, 40%);">+              <xsl:element name="tuple"></span><br><span>                   <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select=".//gp:location-info"/></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select=".//gp:usage-rules"/></span><br><span style="color: hsl(0, 100%, 40%);">-                       <xsl:apply-templates select=".//gp:method"/></span><br><span style="color: hsl(0, 100%, 40%);">-                    <xsl:apply-templates select=".//gp:note-well"/></span><br><span style="color: hsl(0, 100%, 40%);">-                 <xsl:if test="./dm:timestamp"></span><br><span style="color: hsl(0, 100%, 40%);">-                          <timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <xsl:value-of select="./dm:timestamp"/></span><br><span style="color: hsl(0, 100%, 40%);">-                         </timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                      </xsl:if></span><br><span style="color: hsl(120, 100%, 40%);">+                       <xsl:call-template name="geopriv"/></span><br><span style="color: hsl(120, 100%, 40%);">+                   <xsl:apply-templates select="./def:timestamp"/></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="dm:device|dm:person"></span><br><span style="color: hsl(120, 100%, 40%);">+            <xsl:element name="{local-name(.)}"></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:call-template name="geopriv"/></span><br><span style="color: hsl(120, 100%, 40%);">+                   <xsl:apply-templates select="./dm:timestamp"/></span><br><span style="color: hsl(120, 100%, 40%);">+                        <!-- deviceID should only apply to devices --></span><br><span>                         <xsl:if test="./dm:deviceID"></span><br><span>                                <deviceID></span><br><span>                                     <xsl:value-of select="./dm:deviceID"/></span><br><span>@@ -77,63 +91,69 @@</span><br><span>                 </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="def:tuple"></span><br><span style="color: hsl(0, 100%, 40%);">-                <xsl:element name="tuple"></span><br><span style="color: hsl(0, 100%, 40%);">-                      <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select=".//gp:location-info"/></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select=".//gp:usage-rules"/></span><br><span style="color: hsl(0, 100%, 40%);">-                       <xsl:apply-templates select=".//gp:method"/></span><br><span style="color: hsl(0, 100%, 40%);">-                    <xsl:apply-templates select=".//gp:note-well"/></span><br><span style="color: hsl(0, 100%, 40%);">-                 <xsl:if test="./timestamp"></span><br><span style="color: hsl(0, 100%, 40%);">-                             <timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <xsl:value-of select="./timestamp"/></span><br><span style="color: hsl(0, 100%, 40%);">-                            </timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                      </xsl:if></span><br><span style="color: hsl(0, 100%, 40%);">-         </xsl:element></span><br><span style="color: hsl(0, 100%, 40%);">-    </xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   <xsl:template match="dm:person"></span><br><span style="color: hsl(0, 100%, 40%);">-                <xsl:element name="person"></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select=".//gp:location-info"/></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select=".//gp:usage-rules"/></span><br><span style="color: hsl(0, 100%, 40%);">-                       <xsl:apply-templates select=".//gp:method"/></span><br><span style="color: hsl(0, 100%, 40%);">-                    <xsl:apply-templates select=".//gp:note-well"/></span><br><span style="color: hsl(0, 100%, 40%);">-                 <xsl:if test="./dm:timestamp"></span><br><span style="color: hsl(0, 100%, 40%);">-                          <timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <xsl:value-of select="./dm:timestamp"/></span><br><span style="color: hsl(0, 100%, 40%);">-                         </timestamp></span><br><span style="color: hsl(0, 100%, 40%);">-                      </xsl:if></span><br><span style="color: hsl(0, 100%, 40%);">-         </xsl:element></span><br><span style="color: hsl(0, 100%, 40%);">-    </xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   <xsl:template match="gp:location-info/gml:*"></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:geopriv/gp:location-info"></span><br><span>           <xsl:element name="location-info"></span><br><span style="color: hsl(0, 100%, 40%);">-                      <xsl:attribute name="format">gml</xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                  <xsl:call-template name="shape" /></span><br><span style="color: hsl(120, 100%, 40%);">+                    <xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+                            <xsl:when test="ca:civicAddress"></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:when></span><br><span style="color: hsl(120, 100%, 40%);">+                             <xsl:when test="gml:*"></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:when></span><br><span style="color: hsl(120, 100%, 40%);">+                             <xsl:when test="gs:*"></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:when></span><br><span style="color: hsl(120, 100%, 40%);">+                     </xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+                   <xsl:apply-templates/>  <!-- Down we go! --></span><br><span>             </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="gp:location-info/gs:*"></span><br><span style="color: hsl(0, 100%, 40%);">-            <xsl:element name="location-info"></span><br><span style="color: hsl(0, 100%, 40%);">-                      <xsl:attribute name="format">gml</xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                  <xsl:call-template name="shape" /></span><br><span style="color: hsl(0, 100%, 40%);">-              </xsl:element></span><br><span style="color: hsl(0, 100%, 40%);">-    </xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ <!-- Civic Address --></span><br><span>         <xsl:template match="gp:location-info/ca:civicAddress"></span><br><span style="color: hsl(0, 100%, 40%);">-         <xsl:element name="location-info"></span><br><span style="color: hsl(0, 100%, 40%);">-                      <xsl:attribute name="format">civicAddress</xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                 <xsl:call-template name="civicAddress" /></span><br><span style="color: hsl(120, 100%, 40%);">+             <xsl:element name="civicAddress"></span><br><span style="color: hsl(120, 100%, 40%);">+                     <xsl:attribute name="lang"><xsl:value-of select="@xml:lang"/></xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+                   <!-- The for-each seems to be slightly faster than applying another template --></span><br><span style="color: hsl(120, 100%, 40%);">+                        <xsl:for-each select="./*"></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:for-each></span><br><span>                </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <!--</span><br><span style="color: hsl(0, 100%, 40%);">-         All of the "following-sibling" things just stick a comma after the value if there's another</span><br><span style="color: hsl(0, 100%, 40%);">-               element after it.  The result should be...</span><br><span style="color: hsl(120, 100%, 40%);">+    <!-- End of Civic Address.  Back up to location-info. --></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-             name1="value1", name2="value2"</span><br><span style="color: hsl(0, 100%, 40%);">-      --></span><br><span style="color: hsl(120, 100%, 40%);">+        <!-- The GML shapes:  gml:Point, gs:Circle, etc. --></span><br><span style="color: hsl(120, 100%, 40%);">+    <xsl:template match="gp:location-info/gml:*|gp:location-info/gs:*"></span><br><span style="color: hsl(120, 100%, 40%);">+           <xsl:element name="{local-name(.)}"></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'"></span><br><span style="color: hsl(120, 100%, 40%);">+                             <xsl:attribute name="srsName">2d</xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+                        </xsl:when></span><br><span style="color: hsl(120, 100%, 40%);">+                     <xsl:when test="@srsName = 'urn:ogc:def:crs:EPSG::4979'"></span><br><span style="color: hsl(120, 100%, 40%);">+                             <xsl:attribute name="srsName">3d</xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+                        </xsl:when></span><br><span style="color: hsl(120, 100%, 40%);">+                     <xsl:otherwise></span><br><span style="color: hsl(120, 100%, 40%);">+                         <xsl:attribute name="srsName">unknown</xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+                   </xsl:otherwise></span><br><span style="color: hsl(120, 100%, 40%);">+                        </xsl:choose></span><br><span style="color: hsl(120, 100%, 40%);">+                   <xsl:apply-templates />  <!-- Down we go! --></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%);">+       <!-- The supported GML attributes --></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%);">+      <!-- The GML attribute types --></span><br><span>       <xsl:template name="name-value"></span><br><span>             <xsl:element name="{local-name(.)}"></span><br><span>                         <xsl:value-of select="normalize-space(.)"/></span><br><span>@@ -154,58 +174,39 @@</span><br><span>          </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="gs:orientation"><xsl:call-template name="angle" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-    <xsl:template match="gs:radius"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-        <xsl:template match="gs:height"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-        <xsl:template match="gs:semiMajorAxis"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">- <xsl:template match="gs:semiMinorAxis"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">- <xsl:template match="gs:verticalAxis"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-  <xsl:template match="gs:innerRadius"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-   <xsl:template match="gs:outerRadius"><xsl:call-template name="length" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-   <xsl:template match="gs:startAngle"><xsl:call-template name="angle" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-     <xsl:template match="gs:openingAngle"><xsl:call-template name="angle" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-   <xsl:template match="gml:pos"><xsl:call-template name="name-value" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-      <xsl:template match="gml:posList"><xsl:call-template name="name-value" /></xsl:template></span><br><span style="color: hsl(120, 100%, 40%);">+        <!-- End of GML.  Back up to location-info --></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        <xsl:template name="shape"></span><br><span style="color: hsl(120, 100%, 40%);">+   <xsl:template match="gp:location-info/con:confidence"></span><br><span>               <xsl:element name="{local-name(.)}"></span><br><span style="color: hsl(0, 100%, 40%);">-                    <xsl:choose></span><br><span style="color: hsl(0, 100%, 40%);">-                      <xsl:when test="@srsName = 'urn:ogc:def:crs:EPSG::4326'"></span><br><span style="color: hsl(0, 100%, 40%);">-                               <xsl:attribute name="srsName">2d</xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                  </xsl:when></span><br><span style="color: hsl(0, 100%, 40%);">-                       <xsl:when test="@srsName = 'urn:ogc:def:crs:EPSG::4979'"></span><br><span style="color: hsl(0, 100%, 40%);">-                               <xsl:attribute name="srsName">3d</xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                  </xsl:when></span><br><span style="color: hsl(0, 100%, 40%);">-                       <xsl:otherwise></span><br><span style="color: hsl(0, 100%, 40%);">-                           <xsl:attribute name="srsName">unknown</xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                     </xsl:otherwise></span><br><span style="color: hsl(0, 100%, 40%);">-                  </xsl:choose></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates /></span><br><span style="color: hsl(120, 100%, 40%);">+                 <xsl:attribute name="pdf"><xsl:value-of select="@pdf"/></xsl:attribute></span><br><span style="color: hsl(120, 100%, 40%);">+                 <xsl:value-of select="normalize-space(.)" /></span><br><span>                 </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="ca:civicAddress/*"><xsl:call-template name="name-value" /></xsl:template></span><br><span style="color: hsl(0, 100%, 40%);">-    <xsl:template name="civicAddress"></span><br><span style="color: hsl(0, 100%, 40%);">-              <xsl:element name="{local-name(.)}"></span><br><span style="color: hsl(0, 100%, 40%);">-                    <xsl:attribute name="lang"><xsl:value-of select="@xml:lang"/></xsl:attribute></span><br><span style="color: hsl(0, 100%, 40%);">-                     <xsl:apply-templates select="./*"/></span><br><span style="color: hsl(120, 100%, 40%);">+   <!-- End of location-info.  Back up to geopriv --></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    <xsl:template match="gp:geopriv/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:for-each select="./*"></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:for-each></span><br><span>                </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="gp:usage-rules/*"></span><br><span style="color: hsl(120, 100%, 40%);">+       <xsl:template match="gp:geopriv/gp:method"></span><br><span>          <xsl:call-template name="name-value" /></span><br><span>      </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="gp:usage-rules"></span><br><span style="color: hsl(0, 100%, 40%);">-           <xsl:element name="usage-rules"></span><br><span style="color: hsl(0, 100%, 40%);">-                        <xsl:apply-templates /></span><br><span style="color: hsl(120, 100%, 40%);">+ <xsl:template match="gp:geopriv/gp:note-well"></span><br><span style="color: hsl(120, 100%, 40%);">+                <xsl:element name="note-well"></span><br><span style="color: hsl(120, 100%, 40%);">+                        <xsl:value-of select="." /></span><br><span>          </xsl:element></span><br><span>         </xsl:template></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       <xsl:template match="gp:method"></span><br><span style="color: hsl(0, 100%, 40%);">-                <xsl:element name="method"></span><br><span style="color: hsl(0, 100%, 40%);">-             <xsl:value-of select="normalize-space(.)" /></span><br><span style="color: hsl(0, 100%, 40%);">-            </xsl:element></span><br><span style="color: hsl(120, 100%, 40%);">+  <!-- End of geopriv.  Back up to device/tuple/person --></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      <xsl:template match="def:timestamp|dm:timestamp"></span><br><span style="color: hsl(120, 100%, 40%);">+             <xsl:call-template name="name-value" /></span><br><span>      </xsl:template></span><br><span> </span><br><span> </span><br><span>diff --git a/res/res_geolocation/wiki/AsteriskImplementation.md b/res/res_geolocation/wiki/AsteriskImplementation.md</span><br><span>index e818c72..ec1dad6 100644</span><br><span>--- a/res/res_geolocation/wiki/AsteriskImplementation.md</span><br><span>+++ b/res/res_geolocation/wiki/AsteriskImplementation.md</span><br><span>@@ -69,6 +69,11 @@</span><br><span> * GML: A set of sub-parameters that describe the location.</span><br><span> Example: {{location_info = shape=Circle, pos="39.12345 -105.98766", radius=100}}</span><br><span> See the [GML] page for more info.|</span><br><span style="color: hsl(120, 100%, 40%);">+|confidence|no|no|yes|This is a rarely used field in the specification that would indicate the confidence in the location specified.  See [RFC7459|https://www.rfc-editor.org/rfc/rfc7459] for exact details.</span><br><span style="color: hsl(120, 100%, 40%);">+Sub-parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+* {{pdf}}: One of: "unknown", "normal", "rectangular".</span><br><span style="color: hsl(120, 100%, 40%);">+* {{value}}: A percentage indicating the confidence.</span><br><span style="color: hsl(120, 100%, 40%);">+|</span><br><span> </span><br><span> </span><br><span> h2. Profile</span><br><span>@@ -78,14 +83,15 @@</span><br><span> |type|yes|no|no|Must be "profile"|</span><br><span> |location_reference|no|no|no|Specifies the id of a Location object to use.|</span><br><span> |pidf_element|no|no|no|For Civic Address and GML location formats, this parameter specifies the PIDF element that will carry the location description on outgoing SIP requests.  Must be one of "tuple", "device" or "person".  The default is "device".|</span><br><span style="color: hsl(0, 100%, 40%);">-|allow_use_for_routing|no|no|no|This value controls the value of the {{Geolocation-Routing}} header sent on SIP requests,  Must be "yes" or "no".  The default is "no".</span><br><span style="color: hsl(120, 100%, 40%);">+|allow_routing_use|no|no|no|This value controls the value of the {{Geolocation-Routing}} header sent on SIP requests,  Must be "yes" or "no".  The default is "no".</span><br><span> See [RFC6442|Geolocation Reference Information#rfc6442] for more information.|</span><br><span style="color: hsl(0, 100%, 40%);">-|action|no|no|no|Specifies what should be done with any incoming location descriptions received by a channel referencing this profile.\\</span><br><span style="color: hsl(0, 100%, 40%);">-* {{discard}}: Discard any incoming location descriptions and use only the location description specified by {{location_reference}} (if any).\\</span><br><span style="color: hsl(0, 100%, 40%);">-* {{append}}: Append any incoming location descriptions to the one specified by {{location_reference}} (if any).\\</span><br><span style="color: hsl(0, 100%, 40%);">-* {{prepend}}: Prepend any incoming location descriptions to the one specified by {{location_reference}} (if any).\\</span><br><span style="color: hsl(0, 100%, 40%);">-* {{replace}}: Replace the location description specified by {{location_reference}} (if any) with the ones received.\\</span><br><span style="color: hsl(0, 100%, 40%);">-*WARNING*: Using the {{append}} or {{prepend}} options can cause _multiple_ location objects to be sent to a recipient. [RFC5491|Geolocation Reference Information#rfc5491] discourages the use of multiple location objects but has rules that should be followed if it's necessary.  Unfortunately, as is typical for RFCs, there are many "SHOULD"s and very few "MUST"s in the rules so you should read that RFC carefully before you allow multiple locations.|</span><br><span style="color: hsl(120, 100%, 40%);">+|profile_precedence|no|no|no|Specifies which of the available profiles (configured or incoming) takes precedence.\\</span><br><span style="color: hsl(120, 100%, 40%);">+NOTE: On an incoming call leg/channel, the "incoming" profile is the one received by the channel driver from the calling party in the SIP INVITE and the "configured" profile is the one attached to the calling party's pjsip endpoint.  On an outgoing call segment/channel, the "incoming" profile is the one received by the channel driver from the Asterisk core/dialplan and the "configured" profile one is the one attached to the called party's pjsip endpoint.</span><br><span style="color: hsl(120, 100%, 40%);">+* {{prefer_incoming}}: Use the incoming profile if it exists and has location information, otherwise use the       configured profile if it has location information. If neither profile has location information, nothing is sent.</span><br><span style="color: hsl(120, 100%, 40%);">+* {{force_incoming}}: Discard any configured profile and use the incoming profile if it exists and it has location information.  If the incoming profile doesn't exist or has no location information, nothing is sent.</span><br><span style="color: hsl(120, 100%, 40%);">+* {{prefer_config}}: Use the configured profile if it exists and has location information, otherwise use the     incoming profile if it exists and has location information. If neither profile has location                                                     information, nothing is sent.</span><br><span style="color: hsl(120, 100%, 40%);">+* {{force_config}}: Discard any incoming profile and use the configured profile if it exists and it has location information.  If the configured profile doesn't exist or has no location information, nothing is sent.</span><br><span style="color: hsl(120, 100%, 40%);">+|</span><br><span> |usage_rules|no|yes|yes|For Civic Address and GML location formats, this parameter specifies the contents of the {{usage-rules}} PIDF-LO element.\\</span><br><span> * {{retransmission-allowed}}: Must be "yes" or "no".  The default is "no".\\</span><br><span> * {{retention-expires}}: An ISO-format timestamp after which the recipient MUST discard and location information associated with this request.  The default is 24 hours after the request was sent.  You can use dialplan functions to create a timestamp yourself if needed.  For example, to set the timestamp to 1 hour after the request is sent, use:</span><br><span>diff --git a/res/res_pjsip_geolocation.c b/res/res_pjsip_geolocation.c</span><br><span>index c4ba003..0ca1e58 100644</span><br><span>--- a/res/res_pjsip_geolocation.c</span><br><span>+++ b/res/res_pjsip_geolocation.c</span><br><span>@@ -36,6 +36,7 @@</span><br><span> #include "asterisk/res_pjsip_session.h"</span><br><span> </span><br><span> static pj_str_t GEOLOCATION_HDR;</span><br><span style="color: hsl(120, 100%, 40%);">+static pj_str_t GEOLOCATION_ROUTING_HDR;</span><br><span> </span><br><span> static int find_pidf(const char *session_name, struct pjsip_rx_data *rdata, char *geoloc_uri,</span><br><span>    char **pidf_body, unsigned int *pidf_len)</span><br><span>@@ -94,6 +95,42 @@</span><br><span>       return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int add_eprofile_to_channel(struct ast_sip_session *session,</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_geoloc_eprofile *eprofile, struct ast_str * buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *session_name = (session ? ast_sip_session_get_name(session) : "NULL_SESSION");</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_datastore *ds = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   SCOPE_ENTER(4, "%s\n", session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ds = ast_geoloc_datastore_create(session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ds) {</span><br><span style="color: hsl(120, 100%, 40%);">+            SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,</span><br><span style="color: hsl(120, 100%, 40%);">+                     "%s: Couldn't allocate a geoloc datastore\n", session_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%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * We want the datastore to pass through the dialplan and the core</span><br><span style="color: hsl(120, 100%, 40%);">+     * so we need to turn inheritance on.</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_geoloc_datastore_set_inheritance(ds, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_datastore_free(ds);</span><br><span style="color: hsl(120, 100%, 40%);">+               SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,</span><br><span style="color: hsl(120, 100%, 40%);">+                     "%s: Couldn't add eprofile '%s' to datastore\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                  eprofile->id);</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_channel_lock(session->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_datastore_add(session->channel, ds);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_unlock(session->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    SCOPE_EXIT_RTN_VALUE(0, "%s: eprofile: '%s' EffectiveLoc: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+            session_name, eprofile->id, ast_str_buffer(</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_variable_list_join(eprofile->effective_location, ",", "=", NULL, &buf)));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static int handle_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)</span><br><span> {</span><br><span>@@ -101,14 +138,16 @@</span><br><span>     struct ast_sip_endpoint *endpoint = (session ? session->endpoint : NULL);</span><br><span>         struct ast_channel *channel = (session ? session->channel : NULL);</span><br><span>        RAII_VAR(struct ast_geoloc_profile *, config_profile, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-       RAII_VAR(struct ast_geoloc_eprofile *, eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+  RAII_VAR(struct ast_geoloc_eprofile *, config_eprofile, NULL, ao2_cleanup);</span><br><span>  RAII_VAR(struct ast_datastore *, ds, NULL, ast_datastore_free);</span><br><span style="color: hsl(0, 100%, 40%);">- size_t eprofile_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    RAII_VAR(struct ast_geoloc_eprofile *, incoming_eprofile, NULL, ao2_cleanup);</span><br><span>        char *geoloc_hdr_value = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *geoloc_routing_hdr_value = NULL;</span><br><span>       char *geoloc_uri = NULL;</span><br><span>     int rc = 0;</span><br><span>  RAII_VAR(struct ast_str *, buf, ast_str_create(1024), ast_free);</span><br><span>     pjsip_generic_string_hdr *geoloc_hdr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  pjsip_generic_string_hdr *geoloc_routing_hdr = NULL;</span><br><span>         SCOPE_ENTER(3, "%s\n", session_name);</span><br><span> </span><br><span>  if (!session) {</span><br><span>@@ -130,7 +169,13 @@</span><br><span>                       session_name);</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * We don't need geoloc_hdr or geoloc_routing_hdr for a while but we get it now</span><br><span style="color: hsl(120, 100%, 40%);">+    * for trace purposes.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span>  geoloc_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &GEOLOCATION_HDR, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+  geoloc_routing_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,</span><br><span style="color: hsl(120, 100%, 40%);">+               &GEOLOCATION_ROUTING_HDR, NULL);</span><br><span> </span><br><span>     if (!geoloc_hdr) {</span><br><span>           ast_trace(4, "%s: Message has no Geolocation header\n", session_name);</span><br><span>@@ -143,11 +188,11 @@</span><br><span>             if (geoloc_hdr) {</span><br><span>                    SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Message has Geolocation header '"</span><br><span>                                 PJSTR_PRINTF_SPEC "' but endpoint has no geoloc_incoming_call_profile. "</span><br><span style="color: hsl(0, 100%, 40%);">-                          "Geolocation info discarded.\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Done.\n", session_name,</span><br><span>                           PJSTR_PRINTF_VAR(geoloc_hdr->hvalue));</span><br><span>            } else {</span><br><span>                     SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Endpoint has no geoloc_incoming_call_profile. "</span><br><span style="color: hsl(0, 100%, 40%);">-                          "Skipping.\n", session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                               "Done.\n", session_name);</span><br><span>          }</span><br><span>    }</span><br><span> </span><br><span>@@ -156,252 +201,177 @@</span><br><span>              if (geoloc_hdr) {</span><br><span>                    SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Message has Geolocation header '"</span><br><span>                                 PJSTR_PRINTF_SPEC "' but endpoint's geoloc_incoming_call_profile doesn't exist. "</span><br><span style="color: hsl(0, 100%, 40%);">-                         "Geolocation info discarded.\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Done.\n", session_name,</span><br><span>                           PJSTR_PRINTF_VAR(geoloc_hdr->hvalue));</span><br><span>            } else {</span><br><span>                     SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Message has no Geolocation header and endpoint has "</span><br><span style="color: hsl(0, 100%, 40%);">-                             " an invalid geoloc_incoming_call_profile.  Nothing to do..\n", session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                              " an invalid geoloc_incoming_call_profile. Done.\n", session_name);</span><br><span>                }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ds = ast_geoloc_datastore_create(session_name);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING,</span><br><span style="color: hsl(0, 100%, 40%);">-                        "%s: Couldn't allocate a geoloc datastore\n", session_name);</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%);">-       * We want the datastore to pass through the dialplan and the core</span><br><span style="color: hsl(0, 100%, 40%);">-       * so we need to turn inheritance on.</span><br><span style="color: hsl(0, 100%, 40%);">-    */</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_geoloc_datastore_set_inheritance(ds, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    switch (config_profile->action) {</span><br><span style="color: hsl(0, 100%, 40%);">-    case AST_GEOLOC_ACT_DISCARD_INCOMING:</span><br><span style="color: hsl(0, 100%, 40%);">-           if (geoloc_hdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_trace(4, "%s: Profile '%s' location_disposition is 'discard_incoming' so "</span><br><span style="color: hsl(0, 100%, 40%);">-                                "discarding Geolocation: " PJSTR_PRINTF_SPEC "\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                            ast_sorcery_object_get_id(config_profile),</span><br><span style="color: hsl(0, 100%, 40%);">-                              PJSTR_PRINTF_VAR(geoloc_hdr->hvalue));</span><br><span style="color: hsl(0, 100%, 40%);">-               } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_trace(4, "%s: Profile '%s' location_disposition is 'discard_incoming' but there was no Geolocation header"</span><br><span style="color: hsl(0, 100%, 40%);">-                                "so there's nothing to discard\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                                session_name, ast_sorcery_object_get_id(config_profile));</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%);">-               eprofile = ast_geoloc_eprofile_create_from_profile(config_profile);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING, "%s: Unable to create eprofile from "</span><br><span style="color: hsl(120, 100%, 40%);">+      if (config_profile->precedence != AST_GEOLOC_PRECED_DISCARD_CONFIG) {</span><br><span style="color: hsl(120, 100%, 40%);">+              config_eprofile = ast_geoloc_eprofile_create_from_profile(config_profile);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!config_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_log(LOG_WARNING, "%s: Unable to create config_eprofile from "</span><br><span>                          "profile '%s'\n", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span>                }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (!eprofile->effective_location) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Configured profile has no effective location.  Skipping."</span><br><span style="color: hsl(0, 100%, 40%);">-                                "profile '%s'\n", session_name, ast_sorcery_object_get_id(eprofile));</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (config_eprofile && config_eprofile->effective_location) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_trace(4, "%s: config eprofile '%s' has effective location\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           session_name, config_eprofile->id);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-              rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (rc <= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING,</span><br><span style="color: hsl(0, 100%, 40%);">-                                "%s: Couldn't add eprofile '%s' to datastore\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                            eprofile->id);</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (!geoloc_hdr || config_profile->precedence == AST_GEOLOC_PRECED_DISCARD_INCOMING ||</span><br><span style="color: hsl(120, 100%, 40%);">+                             config_profile->precedence == AST_GEOLOC_PRECED_PREFER_CONFIG) {</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         ast_channel_lock(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_channel_datastore_add(channel, ds);</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_channel_unlock(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-            /* We gave the datastore to the channel so don't let RAII_VAR clean it up. */</span><br><span style="color: hsl(0, 100%, 40%);">-               ds = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                            ast_trace(4, "%s: config eprofile '%s' is being used\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    session_name, config_eprofile->id);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-              ast_trace(4, "ep: '%s' EffectiveLoc: %s\n", eprofile->id, ast_str_buffer(</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_variable_list_join(eprofile->effective_location, ",", "=", NULL, &buf)));</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_str_reset(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+                           /*</span><br><span style="color: hsl(120, 100%, 40%);">+                             * If we have an effective location and there's no geolocation header,</span><br><span style="color: hsl(120, 100%, 40%);">+                             * or the action is either DISCARD_INCOMING or PREFER_CONFIG,</span><br><span style="color: hsl(120, 100%, 40%);">+                          * we don't need to even look for a Geolocation header so just add the</span><br><span style="color: hsl(120, 100%, 40%);">+                             * config eprofile to the channel and exit.</span><br><span style="color: hsl(120, 100%, 40%);">+                            */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         /* We discarded the Geolocation header so there's no need to go on. */</span><br><span style="color: hsl(0, 100%, 40%);">-              SCOPE_EXIT_RTN_VALUE(0, "%s: Added geoloc datastore with 1 eprofile from config\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                   session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                                rc = add_eprofile_to_channel(session, config_eprofile, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              "%s: Couldn't add config eprofile '%s' to datastore. Fail.\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                                            config_eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+                              }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   case AST_GEOLOC_ACT_DISCARD_CONFIG:</span><br><span style="color: hsl(0, 100%, 40%);">-             if (geoloc_hdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_trace(4, "%s: Profile '%s' location_disposition is 'discard_config' so "</span><br><span style="color: hsl(0, 100%, 40%);">-                          "discarding config profile\n", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span style="color: hsl(0, 100%, 40%);">-                      /* We process the Geolocation header down below. */</span><br><span style="color: hsl(0, 100%, 40%);">-             } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* Discarded the config and there's no Geolocation header so we're done. */</span><br><span style="color: hsl(0, 100%, 40%);">-                     SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Profile '%s' location_disposition is 'discard_config' but "</span><br><span style="color: hsl(0, 100%, 40%);">-                              "there was no Geolocation header so there's nothing left to process\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                           session_name, ast_sorcery_object_get_id(config_profile));</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-               break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  case AST_GEOLOC_ACT_PREFER_CONFIG:</span><br><span style="color: hsl(0, 100%, 40%);">-              eprofile = ast_geoloc_eprofile_create_from_profile(config_profile);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING, "%s: Unable to create eprofile from "</span><br><span style="color: hsl(0, 100%, 40%);">-                                "profile '%s'\n", session_name, ast_sorcery_object_get_id(config_profile));</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%);">-               if (!eprofile->effective_location) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 if (geoloc_hdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-                               ast_trace(4, "%s: Profile '%s' location_disposition is 'prefer_config' but the configured"</span><br><span style="color: hsl(0, 100%, 40%);">-                                    "eprofile has no location information.  Falling back to Geolocation: "</span><br><span style="color: hsl(0, 100%, 40%);">-                                        PJSTR_PRINTF_SPEC "\n", session_name, ast_sorcery_object_get_id(config_profile),</span><br><span style="color: hsl(0, 100%, 40%);">-                              PJSTR_PRINTF_VAR(geoloc_hdr->hvalue));</span><br><span style="color: hsl(0, 100%, 40%);">-                               /* We process the Geolocation header down below. */</span><br><span style="color: hsl(0, 100%, 40%);">-                     } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE, "%s: Configured profile '%s' has no effective location"</span><br><span style="color: hsl(0, 100%, 40%);">-                                       " and there was no Geolocation header.  Skipping.\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                                 session_name, ast_sorcery_object_get_id(eprofile));</span><br><span style="color: hsl(120, 100%, 40%);">+                           SCOPE_EXIT_RTN_VALUE(0, "%s: Added geoloc datastore with eprofile from config. Done.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    session_name);</span><br><span>                       }</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</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%);">-               rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (rc <= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING,</span><br><span style="color: hsl(0, 100%, 40%);">-                                "%s: Couldn't add eprofile '%s' to datastore\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                            eprofile->id);</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%);">-               ast_channel_lock(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_channel_datastore_add(channel, ds);</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_channel_unlock(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-            /* We gave the datastore to the channel so don't let RAII_VAR clean it up. */</span><br><span style="color: hsl(0, 100%, 40%);">-               ds = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              if (geoloc_hdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_trace(4, "%s: Profile '%s' location_disposition is 'prefer_config' so "</span><br><span style="color: hsl(0, 100%, 40%);">-                           "discarding Geolocation: " PJSTR_PRINTF_SPEC "\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                          session_name, ast_sorcery_object_get_id(config_profile), PJSTR_PRINTF_VAR(geoloc_hdr->hvalue));</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%);">-               ast_trace(4, "ep: '%s' EffectiveLoc: %s\n", eprofile->id, ast_str_buffer(</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_variable_list_join(eprofile->effective_location, ",", "=", NULL, &buf)));</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_str_reset(buf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-             /* We discarded the Geolocation header so there's no need to go on. */</span><br><span style="color: hsl(0, 100%, 40%);">-              SCOPE_EXIT_RTN_VALUE(0, "%s: Added geoloc datastore with 1 eprofile from config\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                   session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  case AST_GEOLOC_ACT_PREFER_INCOMING:</span><br><span style="color: hsl(0, 100%, 40%);">-            if (geoloc_hdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_trace(4, "%s: Profile '%s' location_disposition is 'replace' so "</span><br><span style="color: hsl(0, 100%, 40%);">-                         "we don't need to do anything with the configured profile", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                         ast_sorcery_object_get_id(config_profile));</span><br><span>          } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">-                         "%s: Profile '%s' location_disposition is 'replace' but there's "</span><br><span style="color: hsl(0, 100%, 40%);">-                         "no Geolocation header and therefore no location info to replace"</span><br><span style="color: hsl(0, 100%, 40%);">-                             "it with\n", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span style="color: hsl(120, 100%, 40%);">+                      /*</span><br><span style="color: hsl(120, 100%, 40%);">+                     * If the config eprofile has no effective location, just get rid</span><br><span style="color: hsl(120, 100%, 40%);">+                      * of it.</span><br><span style="color: hsl(120, 100%, 40%);">+                      */</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_trace(4, "%s: Either config_eprofile didn't exist or it had no effective location\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                               session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      ao2_cleanup(config_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+                 config_eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (config_profile->precedence == AST_GEOLOC_PRECED_DISCARD_INCOMING) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            SCOPE_EXIT_RTN_VALUE(0, "%s: DISCARD_INCOMING set and no config eprofile. Done.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                 session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span>            }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   geoloc_hdr_value = ast_alloca(geoloc_hdr->hvalue.slen + 1);</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_copy_pj_str(geoloc_hdr_value, &geoloc_hdr->hvalue, geoloc_hdr->hvalue.slen + 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>       /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * From RFC-6442:</span><br><span style="color: hsl(0, 100%, 40%);">-        * Geolocation-header = "Geolocation" HCOLON locationValue</span><br><span style="color: hsl(0, 100%, 40%);">-     *                      *( COMMA locationValue )</span><br><span style="color: hsl(0, 100%, 40%);">-         * locationValue      = LAQUOT locationURI RAQUOT</span><br><span style="color: hsl(0, 100%, 40%);">-        *                      *(SEMI geoloc-param)</span><br><span style="color: hsl(0, 100%, 40%);">-     * locationURI        = sip-URI / sips-URI / pres-URI</span><br><span style="color: hsl(0, 100%, 40%);">-    *                        / http-URI / https-URI</span><br><span style="color: hsl(0, 100%, 40%);">-         *                            / cid-url ; (from RFC 2392)</span><br><span style="color: hsl(0, 100%, 40%);">-        *                        / absoluteURI ; (from RFC 3261)</span><br><span style="color: hsl(120, 100%, 40%);">+      * At this point, if we have a config_eprofile, then the action was</span><br><span style="color: hsl(120, 100%, 40%);">+    * PREFER_INCOMING so we're going to keep it as a backup if we can't</span><br><span style="color: hsl(120, 100%, 40%);">+   * get a profile from the incoming message.</span><br><span>   */</span><br><span style="color: hsl(0, 100%, 40%);">-     while((geoloc_uri = ast_strsep(&geoloc_hdr_value, ',', AST_STRSEP_TRIM))) {</span><br><span style="color: hsl(0, 100%, 40%);">-         /* geoloc_uri should now be <scheme:location>[;loc-src=fqdn] */</span><br><span style="color: hsl(0, 100%, 40%);">-           char *pidf_body = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-         unsigned int pidf_len = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-              struct ast_xml_doc *incoming_doc = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-                struct ast_geoloc_eprofile *eprofile = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-            int rc = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         ast_trace(4, "Processing URI '%s'\n", geoloc_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (geoloc_hdr && config_profile->precedence != AST_GEOLOC_PRECED_DISCARD_INCOMING) {</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-            if (geoloc_uri[0] != '<' || strchr(geoloc_uri, '>') == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_log(LOG_WARNING, "%s: Geolocation header has bad URI '%s'.  Skipping\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                            geoloc_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-                    continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span>            /*</span><br><span style="color: hsl(0, 100%, 40%);">-               * If the URI isn't "cid" then we're just going to pass it through.</span><br><span style="color: hsl(120, 100%, 40%);">+          * From RFC-6442:</span><br><span style="color: hsl(120, 100%, 40%);">+              * Geolocation-header = "Geolocation" HCOLON locationValue</span><br><span style="color: hsl(120, 100%, 40%);">+           *                      *( COMMA locationValue )</span><br><span style="color: hsl(120, 100%, 40%);">+               * locationValue      = LAQUOT locationURI RAQUOT</span><br><span style="color: hsl(120, 100%, 40%);">+              *                      *(SEMI geoloc-param)</span><br><span style="color: hsl(120, 100%, 40%);">+           * locationURI        = sip-URI / sips-URI / pres-URI</span><br><span style="color: hsl(120, 100%, 40%);">+          *                        / http-URI / https-URI</span><br><span style="color: hsl(120, 100%, 40%);">+               *                            / cid-url ; (from RFC 2392)</span><br><span style="color: hsl(120, 100%, 40%);">+              *                        / absoluteURI ; (from RFC 3261)</span><br><span>             */</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!ast_begins_with(geoloc_uri, "<cid:")) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           geoloc_hdr_value = ast_alloca(geoloc_hdr->hvalue.slen + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_copy_pj_str(geoloc_hdr_value, &geoloc_hdr->hvalue, geoloc_hdr->hvalue.slen + 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%);">+             * We're going to scan the header value for URIs until we find</span><br><span style="color: hsl(120, 100%, 40%);">+             * one that processes successfully or we run out of URIs.</span><br><span style="color: hsl(120, 100%, 40%);">+              * I.E.  The first good one wins.</span><br><span style="color: hsl(120, 100%, 40%);">+              */</span><br><span style="color: hsl(120, 100%, 40%);">+           while (geoloc_hdr_value && !incoming_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      char *pidf_body = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                       unsigned int pidf_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                    struct ast_xml_doc *incoming_doc = NULL;</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%);">+                 /* We're only going to consider the first URI in the header for now */</span><br><span style="color: hsl(120, 100%, 40%);">+                    geoloc_uri = ast_strsep(&geoloc_hdr_value, ',', AST_STRSEP_TRIM);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (ast_strlen_zero(geoloc_uri) || geoloc_uri[0] != '<' || strchr(geoloc_uri, '>') == NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_log(LOG_WARNING, "%s: Geolocation header has no or bad URI '%s'.  Skipping\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    S_OR(geoloc_uri, "<empty>"));</span><br><span style="color: hsl(120, 100%, 40%);">+                         continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                  ast_trace(4, "Processing URI '%s'\n", geoloc_uri);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                        eprofile = ast_geoloc_eprofile_create_from_uri(geoloc_uri, session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                ast_log(LOG_WARNING, "%s: Unable to create effective profile for URI '%s'.  Skipping\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                                      session_name, geoloc_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-                              continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (!ast_begins_with(geoloc_uri, "<cid:")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             ast_trace(4, "Processing URI '%s'\n", geoloc_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                incoming_eprofile = ast_geoloc_eprofile_create_from_uri(geoloc_uri, session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                            if (!incoming_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     ast_log(LOG_WARNING, "%s: Unable to create effective profile for URI '%s'.  Skipping\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                            session_name, geoloc_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                                    continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             }</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_trace(4, "Processing PIDF-LO '%s'\n", geoloc_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                            rc = find_pidf(session_name, rdata, geoloc_uri, &pidf_body, &pidf_len);</span><br><span style="color: hsl(120, 100%, 40%);">+                               if (rc != 0 || !pidf_body || pidf_len == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             }</span><br><span style="color: hsl(120, 100%, 40%);">+                             ast_trace(5, "Processing PIDF-LO "PJSTR_PRINTF_SPEC "\n", (int)pidf_len, pidf_body);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                            incoming_doc = ast_xml_read_memory(pidf_body, pidf_len);</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (!incoming_doc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                  ast_log(LOG_WARNING, "%s: Unable to parse pidf document for URI '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                            session_name, geoloc_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                                    continue;</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%);">+                           incoming_eprofile = ast_geoloc_eprofile_create_from_pidf(incoming_doc, geoloc_uri, session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                             ast_xml_close(incoming_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                if (!incoming_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     ast_log(LOG_WARNING,</span><br><span style="color: hsl(120, 100%, 40%);">+                                          "%s: Couldn't create incoming_eprofile from pidf\n", session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+                             }</span><br><span>                    }</span><br><span style="color: hsl(0, 100%, 40%);">-               } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_trace(4, "Processing PIDF-LO '%s'\n", geoloc_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                        rc = find_pidf(session_name, rdata, geoloc_uri, &pidf_body, &pidf_len);</span><br><span style="color: hsl(0, 100%, 40%);">-                 if (rc != 0 || !pidf_body || pidf_len == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                           continue;</span><br><span style="color: hsl(0, 100%, 40%);">-                       }</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_trace(5, "Processing PIDF-LO "PJSTR_PRINTF_SPEC "\n", (int)pidf_len, pidf_body);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                        incoming_doc = ast_xml_read_memory(pidf_body, pidf_len);</span><br><span style="color: hsl(0, 100%, 40%);">-                        if (!incoming_doc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                            ast_log(LOG_WARNING, "%s: Unable to parse pidf document for URI '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                                      session_name, geoloc_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-                              continue;</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%);">-                       eprofile = ast_geoloc_eprofile_create_from_pidf(incoming_doc, geoloc_uri, session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                }</span><br><span style="color: hsl(0, 100%, 40%);">-               eprofile->action = config_profile->action;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_trace(4, "Processing URI '%s'.  Adding to datastore\n", geoloc_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-              rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-           ao2_ref(eprofile, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-          if (rc <= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_log(LOG_WARNING, "%s: Unable to add effective profile for URI '%s' to datastore.  Skipping\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                            session_name, geoloc_uri);</span><br><span>           }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (config_profile->action == AST_GEOLOC_ACT_PREFER_CONFIG) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_trace(4, "%s: Profile '%s' location_disposition is 'prepend' so "</span><br><span style="color: hsl(0, 100%, 40%);">-                 "adding to datastore first", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                eprofile = ast_geoloc_eprofile_create_from_profile(config_profile);</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!eprofile) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING, "%s: Unable to create eprofile from"</span><br><span style="color: hsl(0, 100%, 40%);">-                         " profile '%s'\n", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!incoming_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Use the config_eprofile as a backup if there was one */</span><br><span style="color: hsl(120, 100%, 40%);">+            incoming_eprofile = config_eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_cleanup(config_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+         config_eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+               if (geoloc_routing_hdr) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     geoloc_routing_hdr_value = ast_alloca(geoloc_routing_hdr->hvalue.slen + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        ast_copy_pj_str(geoloc_routing_hdr_value, &geoloc_routing_hdr->hvalue,</span><br><span style="color: hsl(120, 100%, 40%);">+                         geoloc_routing_hdr->hvalue.slen + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                      incoming_eprofile->allow_routing_use = ast_true(geoloc_routing_hdr_value);</span><br><span>                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           rc = ast_geoloc_datastore_add_eprofile(ds, eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+     if (incoming_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = add_eprofile_to_channel(session, incoming_eprofile, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (rc != 0) {</span><br><span>                       SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_WARNING,</span><br><span style="color: hsl(0, 100%, 40%);">-                                "%s: Couldn't add eprofile '%s' to datastore\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                            eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+                             "%s: Couldn't add eprofile '%s' to channel. Fail.\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                             incoming_eprofile->id);</span><br><span>           }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           SCOPE_EXIT_RTN_VALUE(0, "%s: Added eprofile '%s' to channel. Done.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      session_name, incoming_eprofile->id);</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   eprofile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">- if (eprofile_count == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              SCOPE_EXIT_RTN_VALUE(0,</span><br><span style="color: hsl(0, 100%, 40%);">-                 "%s: Unable to add any effective profiles.  Not adding datastore to channel.\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      session_name);</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%);">-       ast_channel_lock(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_channel_datastore_add(channel, ds);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-    ds = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      SCOPE_EXIT_RTN_VALUE(0, "%s: Added geoloc datastore with %" PRIu64 " eprofiles\n",</span><br><span style="color: hsl(0, 100%, 40%);">-          session_name, eprofile_count);</span><br><span style="color: hsl(120, 100%, 40%);">+        SCOPE_EXIT_RTN_VALUE(0, "%s: No eprofiles to add to channel. Done.\n",        session_name);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int add_pidf_to_tdata(struct ast_datastore *tempds, struct ast_channel *channel,</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_vector_string *uris, int pidf_index, struct pjsip_tx_data *tdata, const char *session_name)</span><br><span style="color: hsl(120, 100%, 40%);">+static const char *add_eprofile_to_tdata(struct ast_geoloc_eprofile *eprofile, struct ast_channel *channel,</span><br><span style="color: hsl(120, 100%, 40%);">+   struct pjsip_tx_data *tdata, struct ast_str **buf, const char *session_name)</span><br><span> {</span><br><span>    static const pj_str_t from_name = { "From", 4};</span><br><span>    static const pj_str_t cid_name = { "Content-ID", 10 };</span><br><span>@@ -417,9 +387,8 @@</span><br><span>       char id[6];</span><br><span>  size_t alloc_size;</span><br><span>   RAII_VAR(char *, base_cid, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-     const char *final;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *final_doc;</span><br><span>       int rc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     RAII_VAR(struct ast_str *, buf, ast_str_create(1024), ast_free);</span><br><span>     SCOPE_ENTER(3, "%s\n", session_name);</span><br><span> </span><br><span>  /*</span><br><span>@@ -427,8 +396,13 @@</span><br><span>     * in it, skips over the ones not needing PIDF processing and combines the</span><br><span>    * rest into one document.</span><br><span>    */</span><br><span style="color: hsl(0, 100%, 40%);">-     final = ast_geoloc_eprofiles_to_pidf(tempds, channel, &buf, session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_trace(5, "Final pidf: \n%s\n", final);</span><br><span style="color: hsl(120, 100%, 40%);">+  final_doc = ast_geoloc_eprofile_to_pidf(eprofile, channel, buf, session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_trace(5, "Final pidf: \n%s\n", final_doc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!final_doc) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create pidf document from"</span><br><span style="color: hsl(120, 100%, 40%);">+                 " eprofile '%s'\n\n", session_name, eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span> </span><br><span>        /*</span><br><span>    * There _should_ be an SDP already attached to the tdata at this point</span><br><span>@@ -450,7 +424,7 @@</span><br><span> </span><br><span>            rc = pjsip_create_multipart_sdp_body(tdata->pool, tdata_sdp_info->sdp, &multipart_body);</span><br><span>           if (rc != PJ_SUCCESS) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 SCOPE_EXIT_LOG_RTN_VALUE(0, LOG_ERROR, "%s: Unable to create sdp multipart body\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Unable to create sdp multipart body\n",</span><br><span>                             session_name);</span><br><span>               }</span><br><span>    } else {</span><br><span>@@ -458,7 +432,7 @@</span><br><span>       }</span><br><span> </span><br><span>        pidf_part = pjsip_multipart_create_part(tdata->pool);</span><br><span style="color: hsl(0, 100%, 40%);">-        pj_cstr(&pidf_body_text, final);</span><br><span style="color: hsl(120, 100%, 40%);">+  pj_cstr(&pidf_body_text, final_doc);</span><br><span>     pidf_part->body = pjsip_msg_body_create(tdata->pool, &pjsip_media_type_application_pidf_xml.type,</span><br><span>          &pjsip_media_type_application_pidf_xml.subtype, &pidf_body_text);</span><br><span> </span><br><span>@@ -471,10 +445,8 @@</span><br><span>                         ast_generate_random_string(id, sizeof(id)),</span><br><span>                  (int) pj_strlen(&sip_uri->host), pj_strbuf(&sip_uri->host));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  ast_str_set(&buf, 0, "cid:%s", base_cid);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_trace(4, "cid: '%s' uri: '%s' pidf_index: %d\n", base_cid, ast_str_buffer(buf), pidf_index);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      AST_VECTOR_INSERT_AT(uris, pidf_index, ast_strdup(ast_str_buffer(buf)));</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_str_set(buf, 0, "cid:%s", base_cid);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_trace(4, "cid: '%s' uri: '%s'\n", base_cid, ast_str_buffer(*buf));</span><br><span> </span><br><span>         cid_value.ptr = pj_pool_alloc(tdata->pool, alloc_size);</span><br><span>   cid_value.slen = sprintf(cid_value.ptr, "<%s>", base_cid);</span><br><span>@@ -485,7 +457,7 @@</span><br><span> </span><br><span>     tdata->msg->body = multipart_body;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        SCOPE_EXIT_RTN_VALUE(0, "%s: PIDF-LO added with cid '%s'\n", session_name, base_cid);</span><br><span style="color: hsl(120, 100%, 40%);">+       SCOPE_EXIT_RTN_VALUE(ast_str_buffer(*buf), "%s: PIDF-LO added with cid '%s'\n", session_name, base_cid);</span><br><span> }</span><br><span> </span><br><span> static void handle_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)</span><br><span>@@ -495,18 +467,15 @@</span><br><span>     struct ast_channel *channel = session->channel;</span><br><span>   RAII_VAR(struct ast_geoloc_profile *, config_profile, NULL, ao2_cleanup);</span><br><span>    RAII_VAR(struct ast_geoloc_eprofile *, config_eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+   RAII_VAR(struct ast_geoloc_eprofile *, incoming_eprofile, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_geoloc_eprofile *final_eprofile = NULL;</span><br><span>   RAII_VAR(struct ast_str *, buf, ast_str_create(1024), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-        RAII_VAR(struct ast_datastore *, tempds, NULL, ast_datastore_free);</span><br><span>  struct ast_datastore *ds = NULL;  /* The channel cleans up ds */</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_vector_string uris;</span><br><span style="color: hsl(0, 100%, 40%);">-  pjsip_msg_body *orig_body;</span><br><span style="color: hsl(0, 100%, 40%);">-      pjsip_generic_string_hdr *geoloc_hdr;</span><br><span style="color: hsl(0, 100%, 40%);">-   int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        pjsip_msg_body *orig_body = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     pjsip_generic_string_hdr *geoloc_hdr = NULL;</span><br><span>         int eprofile_count = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- int pidf_index = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-    int geoloc_routing = 0;</span><br><span>      int rc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     const char *final;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *uri;</span><br><span>     SCOPE_ENTER(3, "%s\n", session_name);</span><br><span> </span><br><span>  if (!buf) {</span><br><span>@@ -541,136 +510,111 @@</span><br><span>                        "profile '%s'\n", session_name, ast_sorcery_object_get_id(config_profile));</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (config_profile->action != AST_GEOLOC_ACT_PREFER_INCOMING) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ds = ast_geoloc_datastore_find(channel);</span><br><span style="color: hsl(0, 100%, 40%);">-                if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      ast_trace(4, "%s: There was no geoloc datastore\n", session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-            } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        eprofile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(0, 100%, 40%);">-                 ast_trace(4, "%s: There are %d geoloc profiles on this channel\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                              eprofile_count);</span><br><span style="color: hsl(0, 100%, 40%);">-                }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!config_eprofile->effective_location) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If there's no effective location on the eprofile</span><br><span style="color: hsl(120, 100%, 40%);">+                * we don't need to keep it.</span><br><span style="color: hsl(120, 100%, 40%);">+               */</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_trace(4, "%s: There was no effective location for config profile '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       session_name, ast_sorcery_object_get_id(config_profile));</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_ref(config_eprofile, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+         config_eprofile = NULL;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * We don't want to alter the datastore that may (or may not) be on</span><br><span style="color: hsl(0, 100%, 40%);">-  * the channel so we're going to create a temporary one to hold the</span><br><span style="color: hsl(0, 100%, 40%);">-  * config eprofile plus any in the channel datastore.  Technically</span><br><span style="color: hsl(0, 100%, 40%);">-       * we could just use a vector but the datastore already has the logic</span><br><span style="color: hsl(0, 100%, 40%);">-    * to release all the eprofile references and the datastore itself.</span><br><span style="color: hsl(0, 100%, 40%);">-      */</span><br><span style="color: hsl(0, 100%, 40%);">-     tempds = ast_geoloc_datastore_create("temp");</span><br><span style="color: hsl(120, 100%, 40%);">+       ds = ast_geoloc_datastore_find(channel);</span><br><span>     if (!ds) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_trace(4, "%s: There are no geoloc profiles on this channel\n", session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_geoloc_datastore_add_eprofile(tempds, config_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_trace(4, "%s: There was no geoloc datastore on the channel\n", session_name);</span><br><span>  } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (config_profile->action == AST_GEOLOC_ACT_PREFER_CONFIG) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_trace(4, "%s: prepending config_eprofile\n", session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_geoloc_datastore_add_eprofile(tempds, config_eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-               for (i = 0; i < eprofile_count; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       struct ast_geoloc_eprofile *ep = ast_geoloc_datastore_get_eprofile(ds, i);</span><br><span style="color: hsl(0, 100%, 40%);">-                      ast_trace(4, "%s: adding eprofile '%s' from channel\n", session_name, ep->id);</span><br><span style="color: hsl(0, 100%, 40%);">-                     ast_geoloc_datastore_add_eprofile(tempds, ep);</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (config_profile->action == AST_GEOLOC_ACT_PREFER_INCOMING) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      ast_trace(4, "%s: appending config_eprofile\n", session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_geoloc_datastore_add_eprofile(tempds, config_eprofile);</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(120, 100%, 40%);">+             eprofile_count = ast_geoloc_datastore_size(ds);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_trace(4, "%s: There are %d geoloc profiles on this channel\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                    eprofile_count);</span><br><span style="color: hsl(120, 100%, 40%);">+              /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * There'd better be a max of 1 at this time.  In the future</span><br><span style="color: hsl(120, 100%, 40%);">+               * we may allow more than 1.</span><br><span style="color: hsl(120, 100%, 40%);">+           */</span><br><span style="color: hsl(120, 100%, 40%);">+           incoming_eprofile = ast_geoloc_datastore_get_eprofile(ds, 0);</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   eprofile_count = ast_geoloc_datastore_size(tempds);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (eprofile_count == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              SCOPE_EXIT_RTN("%s: There are no profiles left to send\n", session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_trace(4, "%s: There are now %d geoloc profiles to be sent\n", session_name,</span><br><span style="color: hsl(0, 100%, 40%);">-               eprofile_count);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_trace(4, "%s: Profile precedence: %s\n\n", session_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_geoloc_precedence_to_name(config_profile->precedence));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * This vector is going to accumulate all of the URIs that</span><br><span style="color: hsl(0, 100%, 40%);">-       * will need to go on the Geolocation header.</span><br><span style="color: hsl(0, 100%, 40%);">-    */</span><br><span style="color: hsl(0, 100%, 40%);">-     rc = AST_VECTOR_INIT(&uris, 2);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (rc != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-          SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Unable to allocate memory for vector\n", session_name);</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%);">-       * It's possible that we have a list of eprofiles that have both "pass-by-reference (external URI)"</span><br><span style="color: hsl(0, 100%, 40%);">-        * and "pass by value (to go in PIDF)" eprofiles.  The ones that just need a URI added to the</span><br><span style="color: hsl(0, 100%, 40%);">-  * Geolocation header get added to the "uris" vector in this loop. The ones that result in a</span><br><span style="color: hsl(0, 100%, 40%);">-   * PIDF though, need to be combined into a single PIDF-LO document so we're just going to</span><br><span style="color: hsl(0, 100%, 40%);">-    * save the first one's index so we can insert the "cid" header in the right place, then</span><br><span style="color: hsl(0, 100%, 40%);">-   * we'll send the whole list off to add_pidf_to_tdata() so they can be combined into a</span><br><span style="color: hsl(0, 100%, 40%);">-       * single document.</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%);">-     for (i = 0; i < eprofile_count; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               struct ast_geoloc_eprofile *ep = ast_geoloc_datastore_get_eprofile(tempds, i);</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_geoloc_eprofile_refresh_location(ep);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_trace(4, "ep: '%s' EffectiveLoc: %s\n", ep->id, ast_str_buffer(</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_variable_list_join(ep->effective_location, ",", "=", NULL, &buf)));</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_str_reset(buf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-             if (ep->format == AST_GEOLOC_FORMAT_URI) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   final = ast_geoloc_eprofile_to_uri(ep, channel, &buf, session_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_trace(4, "URI: %s\n", final);</span><br><span style="color: hsl(0, 100%, 40%);">-                     AST_VECTOR_APPEND(&uris, ast_strdup(final));</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_str_reset(buf);</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (config_profile->precedence) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case AST_GEOLOC_PRECED_DISCARD_INCOMING:</span><br><span style="color: hsl(120, 100%, 40%);">+              final_eprofile = config_eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_cleanup(incoming_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+               incoming_eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case AST_GEOLOC_PRECED_PREFER_INCOMING:</span><br><span style="color: hsl(120, 100%, 40%);">+               if (incoming_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      final_eprofile = incoming_eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+                   ao2_cleanup(config_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+                 config_eprofile = NULL;</span><br><span>              } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        /*</span><br><span style="color: hsl(0, 100%, 40%);">-                       * If there are GML or civicAddress eprofiles, we need to save the position</span><br><span style="color: hsl(0, 100%, 40%);">-                      * of the first one in relation to any URI ones so we can insert the "cid"</span><br><span style="color: hsl(0, 100%, 40%);">-                     * uri for it in the original position.</span><br><span style="color: hsl(0, 100%, 40%);">-                  */</span><br><span style="color: hsl(0, 100%, 40%);">-                     if (pidf_index < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                pidf_index = i;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(120, 100%, 40%);">+                     final_eprofile = config_eprofile;</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-               /* The LAST eprofile determines routing */</span><br><span style="color: hsl(0, 100%, 40%);">-              geoloc_routing = ep->geolocation_routing;</span><br><span style="color: hsl(0, 100%, 40%);">-            ao2_ref(ep, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case AST_GEOLOC_PRECED_DISCARD_CONFIG:</span><br><span style="color: hsl(120, 100%, 40%);">+                final_eprofile = incoming_eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+           ao2_cleanup(config_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+         config_eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case AST_GEOLOC_PRECED_PREFER_CONFIG:</span><br><span style="color: hsl(120, 100%, 40%);">+         if (config_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        final_eprofile = config_eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+                     ao2_cleanup(incoming_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+                       incoming_eprofile = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      final_eprofile = incoming_eprofile;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * If we found at least one eprofile needing PIDF processing, we'll</span><br><span style="color: hsl(0, 100%, 40%);">-  * send the entire list off to add_pidf_to_tdata().  We're going to save</span><br><span style="color: hsl(0, 100%, 40%);">-     * the pointer to the original tdata body in case we need to revert</span><br><span style="color: hsl(0, 100%, 40%);">-      * if we can't add the headers.</span><br><span style="color: hsl(0, 100%, 40%);">-      */</span><br><span style="color: hsl(0, 100%, 40%);">-     orig_body = tdata->msg->body;</span><br><span style="color: hsl(0, 100%, 40%);">-     if (pidf_index >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-               rc = add_pidf_to_tdata(tempds, channel, &uris, pidf_index, tdata, session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!final_eprofile) {</span><br><span style="color: hsl(120, 100%, 40%);">+                SCOPE_EXIT_RTN("%s: No eprofiles to send.  Done.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        session_name);</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * Now that we have all the URIs in the vector, we'll string them together</span><br><span style="color: hsl(0, 100%, 40%);">-   * to create the data for the Geolocation header.</span><br><span style="color: hsl(0, 100%, 40%);">-        */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_geoloc_eprofile_refresh_location(final_eprofile);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (final_eprofile->format == AST_GEOLOC_FORMAT_URI) {</span><br><span style="color: hsl(120, 100%, 40%);">+             uri = ast_geoloc_eprofile_to_uri(final_eprofile, channel, &buf, session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!uri) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Unable to create URI from eprofile '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                              session_name, final_eprofile->id);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              orig_body = tdata->msg->body;</span><br><span style="color: hsl(120, 100%, 40%);">+           uri = add_eprofile_to_tdata(final_eprofile, channel, tdata, &buf, session_name);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!uri) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   tdata->msg->body = orig_body;</span><br><span style="color: hsl(120, 100%, 40%);">+                   SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Unable to add eprofile '%s' to tdata\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         session_name, final_eprofile->id);</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%);">+   uri = ast_strdupa(ast_str_buffer(buf));</span><br><span>      ast_str_reset(buf);</span><br><span style="color: hsl(0, 100%, 40%);">-     for (i = 0; i < AST_VECTOR_SIZE(&uris); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-           char *uri = AST_VECTOR_GET(&uris, i);</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_trace(4, "ix: %d of %d LocRef: %s\n", i, (int)AST_VECTOR_SIZE(&uris), uri);</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_str_append(&buf, 0, "%s<%s>", (i > 0 ? "," : ""), uri);</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_str_set(&buf, 0, "<%s>", uri);</span><br><span style="color: hsl(120, 100%, 40%);">+        uri = ast_strdupa(ast_str_buffer(buf));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     AST_VECTOR_RESET(&uris, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-  AST_VECTOR_FREE(&uris);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_trace(4, "%s: Using URI '%s'\n", session_name, uri);</span><br><span> </span><br><span>       /* It's almost impossible for add header to fail but you never know */</span><br><span style="color: hsl(0, 100%, 40%);">-      geoloc_hdr = ast_sip_add_header2(tdata, "Geolocation", ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+        geoloc_hdr = ast_sip_add_header2(tdata, "Geolocation", uri);</span><br><span>       if (geoloc_hdr == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-               tdata->msg->body = orig_body;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (orig_body) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      tdata->msg->body = orig_body;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span>            SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Unable to add Geolocation header\n", session_name);</span><br><span>     }</span><br><span style="color: hsl(0, 100%, 40%);">-       rc = ast_sip_add_header(tdata, "Geolocation-Routing", geoloc_routing ? "yes" : "no");</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = ast_sip_add_header(tdata, "Geolocation-Routing", final_eprofile->allow_routing_use ? "yes" : "no");</span><br><span>    if (rc != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-          tdata->msg->body = orig_body;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (orig_body) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      tdata->msg->body = orig_body;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span>            pj_list_erase(geoloc_hdr);</span><br><span>           SCOPE_EXIT_LOG_RTN(LOG_ERROR, "%s: Unable to add Geolocation-Routing header\n", session_name);</span><br><span>     }</span><br><span style="color: hsl(0, 100%, 40%);">-       SCOPE_EXIT_RTN("%s: Geolocation: %s\n", session_name, ast_str_buffer(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ SCOPE_EXIT_RTN("%s: Geolocation: %s\n", session_name, uri);</span><br><span> }</span><br><span> </span><br><span> static struct ast_sip_session_supplement geolocation_supplement = {</span><br><span>@@ -697,6 +641,7 @@</span><br><span> {</span><br><span>     int res = 0;</span><br><span>         GEOLOCATION_HDR = pj_str("Geolocation");</span><br><span style="color: hsl(120, 100%, 40%);">+    GEOLOCATION_ROUTING_HDR = pj_str("Geolocation-Routing");</span><br><span> </span><br><span>       ast_sip_session_register_supplement(&geolocation_supplement);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18953">change 18953</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/+/18953"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18.14 </div>
<div style="display:none"> Gerrit-Change-Id: If38c23f26228e96165be161c2f5e849cb8e16fa0 </div>
<div style="display:none"> Gerrit-Change-Number: 18953 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>