[sr-dev] git:master: modules_k/rls: Added support for XPath within rl-services documents

Peter Dunkley peter.dunkley at crocodile-rcs.com
Fri Aug 5 18:25:10 CEST 2011


Module: sip-router
Branch: master
Commit: 5e8aab47d4b52a30f5f3e1984f5eeb6dd0e529a3
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=5e8aab47d4b52a30f5f3e1984f5eeb6dd0e529a3

Author: pd <peter.dunkley at crocodile-rcs.com>
Committer: pd <peter.dunkley at crocodile-rcs.com>
Date:   Fri Aug  5 17:20:36 2011 +0100

modules_k/rls: Added support for XPath within rl-services documents

- RLS was recently updated to support rl-services index documents that
  "point" to resource-lists.  However, that support only extended to
  indexes that pointed to entire resource-list documents.

  This change enables support for resource lists that "point" to
  specific nodes within a document.

  For example, the following rl-services document would now be supported:

    <?xml version="1.0" encoding="UTF-8"?>
    <rls-services xmlns="urn:ietf:params:xml:ns:rls-services">
      <service uri="sip:alice_all at pd-laptop-linux.croc.internal">
        <resource-list>http://server.example.net:5060/xcap-root/resource-lists/users/sip:alice@example.net/generallist.xml/~~/resource-lists/list%5b@name=%22oma_buddylist%22%5d</resource-list>
        <packages>
            <package>presence</package>
        </packages>
      </service>
    </rls-services>

---

 modules_k/rls/notify.c |  121 +++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 114 insertions(+), 7 deletions(-)

diff --git a/modules_k/rls/notify.c b/modules_k/rls/notify.c
index dd1e58e..e964520 100644
--- a/modules_k/rls/notify.c
+++ b/modules_k/rls/notify.c
@@ -48,6 +48,8 @@
 #include "../../lib/kcore/hash_func.h"
 #include "rls.h"
 #include "notify.h"
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
 
 typedef struct res_param
 {
@@ -1131,6 +1133,7 @@ int parse_xcap_uri(char *uri, str *host, unsigned short *port, str *path)
 	return 1;
 }
 
+#define MAX_PATH_LEN	127
 int rls_get_resource_list(str *rl_uri, str *username, str *domain,
 		xmlNodePtr *rl_node, xmlDocPtr *xmldoc)
 {
@@ -1144,6 +1147,12 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
 	db_val_t *row_vals;
 	int xcap_col;
 	str body;
+	int checked = 0;
+	str root, path = {0, 0};
+	char path_str[MAX_PATH_LEN + 1];
+	xmlXPathContextPtr xpathCtx = NULL;
+	xmlXPathObjectPtr xpathObj = NULL;
+
 
 	if (rl_uri==NULL || username==NULL || domain==NULL)
 	{
@@ -1151,6 +1160,56 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
 		return -1;
 	}
 
+	LM_DBG("rl_uri: %.*s", rl_uri->len, rl_uri->s);
+
+	root.s = rl_uri->s;
+	root.len = rl_uri->len;
+	while (checked < rl_uri->len)
+	{
+		if (checked < rl_uri->len - 3 && strncmp(rl_uri->s + checked, "/~~", 3) == 0)
+		{
+			root.len = checked;
+			checked += 3;
+			break;
+		}
+		checked++;
+	}
+	LM_DBG("doc: %.*s", root.len, root.s);
+
+	memset (path_str, '\0', MAX_PATH_LEN + 1);
+	path.s = path_str;
+	path.len = 0;
+	while (checked < rl_uri->len && path.len <= MAX_PATH_LEN)
+	{
+		if (rl_uri->s[checked] == '/')
+		{
+			strcat(path.s, "/xmlns:");
+			path.len += 7;
+			checked++;
+		}
+		else if (checked <= rl_uri->len - 3 && strncmp(rl_uri->s + checked, "\%5b", 3) == 0)
+		{
+			path.s[path.len++] = '[';
+			checked += 3;
+		}
+		else if (checked <= rl_uri->len - 3 && strncmp(rl_uri->s + checked, "\%5d", 3) == 0)
+		{
+			path.s[path.len++] = ']';
+			checked += 3;
+		}
+		else if (checked <= rl_uri->len - 3 && strncmp(rl_uri->s + checked, "\%22", 3) == 0)
+		{
+			path.s[path.len++] = '\"';
+			checked += 3;
+		}
+		else
+		{
+			path.s[path.len++] = rl_uri->s[checked];
+			checked++;
+		}
+	}
+	LM_DBG("path: %.*s", path.len, path.s);
+
 	query_cols[n_query_cols] = &str_username_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
@@ -1172,7 +1231,7 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
 	query_cols[n_query_cols] = &str_doc_uri_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
-	query_vals[n_query_cols].val.str_val = *rl_uri;
+	query_vals[n_query_cols].val.str_val = root;
 	n_query_cols++;
 
 	if(rls_dbf.use_table(rls_db, &rls_xcap_table) < 0)
@@ -1187,8 +1246,8 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
 	if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
 				n_query_cols, n_result_cols, 0, &result)<0)
 	{
-		LM_ERR("failed querying table xcap for document [rl_uri]=%.*s\n",
-				rl_uri->len, rl_uri->s);
+		LM_ERR("failed querying table xcap for document: %.*s\n",
+				root.len, root.s);
 		if(result)
 			rls_dbf.free_result(rls_db, result);
 		return -1;
@@ -1225,19 +1284,67 @@ int rls_get_resource_list(str *rl_uri, str *username, str *domain,
 		goto error;
 	}
 
-	*rl_node = XMLDocGetNodeByName(*xmldoc,"resource-lists", NULL);
-	if(rl_node==NULL)
+	if (path.len == 0)
 	{
-		LM_ERR("no resource-lists node in XML document\n");
-		goto error;
+		/* No path specified - use all resource-lists. */
+		*rl_node = XMLDocGetNodeByName(*xmldoc,"resource-lists", NULL);
+		if(rl_node==NULL)
+		{
+			LM_ERR("no resource-lists node in XML document\n");
+			goto error;
+		}
 	}
+	else if (path.s != NULL)
+	{
+		xpathCtx = xmlXPathNewContext(*xmldoc);
+		if (xpathCtx == NULL)
+		{
+			LM_ERR("unable to create new XPath context");
+			goto error;
+		}
+
+		if (xmlXPathRegisterNs(xpathCtx, BAD_CAST "xmlns", BAD_CAST "urn:ietf:params:xml:ns:resource-lists") != 0)
+		{
+			LM_ERR("unable to register xmlns\n");
+			goto error;
+		}
+
+		xpathObj = xmlXPathEvalExpression(BAD_CAST path.s, xpathCtx);
+		if (xpathObj == NULL)
+		{
+			LM_ERR("unable to evaluate path\n");
+			goto error;
+		}
 
+		if (xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr <= 0)
+		{
+			LM_ERR("no nodes found\n");
+			goto error;
+		}
+		if (xpathObj->nodesetval->nodeTab[0] != NULL && xpathObj->nodesetval->nodeTab[0]->type != XML_ELEMENT_NODE)
+		{
+			LM_ERR("no nodes of the correct type found\n");
+			goto error;
+
+		}
+
+		*rl_node = xpathObj->nodesetval->nodeTab[0];
+
+		xmlXPathFreeObject(xpathObj);
+		xmlXPathFreeContext(xpathCtx);
+	}
+	
 	rls_dbf.free_result(rls_db, result);
 	return 1;
 
 error:
 	if(result!=NULL)
 		rls_dbf.free_result(rls_db, result);
+	if(xpathObj!=NULL)
+		xmlXPathFreeObject(xpathObj);
+	
+	if(xpathCtx!=NULL)
+		xmlXPathFreeContext(xpathCtx);
 	if(xmldoc!=NULL)
 		xmlFreeDoc(*xmldoc);
 




More information about the sr-dev mailing list