Bläddra i källkod

added functions for MESSAGE authorization

Vaclav Kubart 19 år sedan
förälder
incheckning
fa47786ed2

+ 3 - 0
lib/xcap/ChangeLog

@@ -1,2 +1,5 @@
+2006-03-29
+	* added message authorization functions
+
 2006-03-24
 	* optimized XCAP document access - each process has its own curl handle

+ 223 - 0
lib/xcap/common_policy.c

@@ -0,0 +1,223 @@
+#include <xcap/common_policy.h>
+
+cp_unknown_t *create_unknown(int data_size)
+{
+	cp_unknown_t *u = cds_malloc(sizeof(cp_unknown_t) + data_size);
+	u->next = NULL;
+	return u;
+}
+
+/* ------- freeing used memory for common-rules ------- */
+
+static void free_identity(cp_identity_t *id)
+{
+	cp_id_t *i, *ni;
+	cp_domain_t *d, *nd;
+	cp_except_t *e, *ne;
+	cp_except_domain_t *ed, *ned;
+	
+	if (!id) return;
+	
+	i = id->ids;
+	while (i) {
+		ni = i->next;
+		str_free_content(&i->entity);
+		cds_free(i);
+		i = ni;
+	}
+	
+	d = id->domains;
+	while (d) {
+		nd = d->next;
+		str_free_content(&d->domain);
+		cds_free(d);
+		d = nd;
+	}
+	
+	e = id->excepts;
+	while (e) {
+		ne = e->next;
+		str_free_content(&e->entity);
+		cds_free(e);
+		e = ne;
+	}
+
+	if (id->any_identity) {
+		d = id->any_identity->domains;
+		while (d) {
+			nd = d->next;
+			str_free_content(&d->domain);
+			cds_free(d);
+			d = nd;
+		}
+		
+		ed = id->any_identity->except_domains;
+		while (ed) {
+			ned = ed->next;
+			str_free_content(&ed->domain);
+			cds_free(ed);
+			ed = ned;
+		}
+	}
+	
+	cds_free(id);
+}
+
+static void free_conditions(cp_conditions_t *c)
+{
+	cp_sphere_t *s, *n;
+	if (!c) return;
+	if (c->validity) cds_free(c->validity);
+	if (c->identity) free_identity(c->identity);
+	s = c->spheres;
+	while (s) {
+		n = s->next;
+		str_free_content(&s->value);
+		cds_free(s);
+		s = n;
+	}
+	cds_free(c);
+}
+
+
+static void free_transformations(cp_transformations_t *t)
+{
+	cp_unknown_t *u, *nu;
+	
+	if (!t) return;
+	
+	u = t->unknown;
+	while (u) {
+		nu = u->next;
+		cds_free(u);
+		u = nu;
+	}
+	cds_free(t);
+}
+
+void free_cp_rule(cp_rule_t *r, cp_free_actions_func free_actions)
+{
+	if (!r) return;
+	if (r->conditions) free_conditions(r->conditions);
+	if (r->actions) free_actions(r->actions);
+	if (r->transformations) free_transformations(r->transformations);
+	str_free_content(&r->id);
+	cds_free(r);
+}
+
+void free_common_rules(cp_ruleset_t *r, cp_free_actions_func free_actions)
+{
+	cp_rule_t *rule, *n;
+	
+	if (!r) return;
+	rule = r->rules;
+	while (rule) {
+		n = rule->next;
+		free_cp_rule(rule, free_actions);
+		rule = n;
+	}
+	cds_free(r);
+}
+
+static void parse_uri(const str_t *uri, str_t *user, str_t *domain)
+{
+	char *a;
+	char *d;
+	str_t s;
+	
+	str_clear(user);
+	str_clear(domain);
+	if (uri->len > 0) {
+		d = str_strchr(uri, ':');
+		if (d) {
+			s.s = d + 1;
+			s.len = uri->len - (s.s - uri->s);
+		}
+		else s = *uri;
+		a = str_strchr(&s, '@');
+		if (a) {
+			user->s = s.s;
+			user->len = a - s.s;
+		}
+		domain->s = s.s + user->len;
+		if (a) domain->s++;
+		domain->len = uri->len - (domain->s - uri->s);
+		
+/*		TRACE_LOG("parse uri \'%.*s\': user=\'%.*s\' domain=\'%.*s\'\n",
+				FMT_STR(*uri), FMT_STR(*user), FMT_STR(*domain));*/
+	}
+}
+
+
+/* returns 1 if rule is used for uri */
+int is_rule_for_uri(cp_rule_t *rule, const str_t *uri)
+{	
+	cp_identity_t *id;
+	int ok = 0;
+	str_t domain, user;
+	str_t d_, u_;
+	cp_domain_t *d;
+	cp_id_t *i;
+	cp_except_t *e;
+	cp_except_domain_t *ed;
+	
+	if (!rule) return 0;
+	if (!rule->conditions) return 1; /* FIXME: ??? */
+	id = rule->conditions->identity;
+	if (!id) return 0;
+	
+	parse_uri(uri, &user, &domain);
+	
+	i = id->ids;
+	while (i) {
+		parse_uri(&i->entity, &u_, &d_);
+/*		TRACE_LOG("comparing uris \'%.*s\' \'%.*s\' "
+				"domains \'%.*s\' \'%.*s\'\n", 
+				FMT_STR(user), FMT_STR(u_),
+				FMT_STR(domain), FMT_STR(d_));*/
+		if (str_case_equals(&user, &u_) == 0) {
+			if (str_nocase_equals(&domain, &d_) == 0) {
+/*				TRACE_LOG("id found\n");*/
+				return 1;
+			}
+		}
+		i = i->next;
+	}
+	
+	d = id->domains;
+	while (d) {
+/*		TRACE_LOG("comparing domains \'%.*s\' \'%.*s\'\n",
+				FMT_STR(domain), FMT_STR(d->domain));*/
+		if (str_nocase_equals(&domain, &d->domain) == 0) ok = 1;
+		d = d->next;
+	}
+	if (ok) {
+		e = id->excepts;
+		while (e) {
+			if (str_case_equals(&user, &e->entity) == 0)
+				return 0; /* excepts matched */
+			e = e->next;
+		}
+/*		TRACE_LOG("domain found and excepts not matched\n");*/
+		return 1;
+	}
+
+	if (id->any_identity) {
+		d = id->any_identity->domains;
+		while (d) {
+			if (str_nocase_equals(&domain, &d->domain) == 0) {
+/*				TRACE_LOG("domain matches for anonymous\n");*/
+				return 1;
+			}
+			d = d->next;
+		}
+		
+		ed = id->any_identity->except_domains;
+		while (ed) {
+			if (str_nocase_equals(&domain, &d->domain) == 0) return 0;
+			ed = ed->next;
+		}
+	}
+	return 0;
+}
+

+ 8 - 0
lib/xcap/common_policy.h

@@ -104,4 +104,12 @@ typedef struct {
 	cp_rule_t *rules;
 } cp_ruleset_t;
 
+cp_unknown_t *create_unknown(int data_size);
+
+typedef void (cp_free_actions_func)(cp_actions_t *a);
+
+void free_cp_rule(cp_rule_t *r, cp_free_actions_func free_actions);
+void free_common_rules(cp_ruleset_t *r, cp_free_actions_func free_actions);
+int is_rule_for_uri(cp_rule_t *rule, const str_t *uri);
+
 #endif

+ 140 - 0
lib/xcap/msg_rules.c

@@ -0,0 +1,140 @@
+/* 
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <xcap/msg_rules.h>
+#include <xcap/parse_msg_rules.h>
+#include <xcap/xcap_result_codes.h>
+#include <cds/dstring.h>
+#include <cds/memory.h>
+#include <cds/logger.h>
+#include <cds/list.h>
+#include <cds/sstr.h>
+#include <string.h>
+
+char *xcap_uri_for_msg_rules(const char *xcap_root, const str_t *uri)
+{
+	dstring_t s;
+	int l;
+	char *dst = NULL;
+
+	if (!xcap_root) return NULL;
+	l = strlen(xcap_root);
+	dstr_init(&s, 2 * l + 32);
+	dstr_append(&s, xcap_root, l);
+	if (xcap_root[l - 1] != '/') dstr_append(&s, "/", 1);
+	dstr_append_zt(&s, "im-rules/users/");
+	dstr_append_str(&s, uri);
+	dstr_append_zt(&s, "/im-rules.xml");
+	
+	l = dstr_get_data_length(&s);
+	if (l > 0) {
+		dst = (char *)cds_malloc(l + 1);
+		if (dst) {
+			dstr_get_data(&s, dst);
+			dst[l] = 0;
+		}
+	}
+	dstr_destroy(&s);
+	return dst;
+}
+
+int get_msg_rules(const char *xcap_root, const str_t *uri, xcap_query_params_t *xcap_params, msg_rules_t **dst)
+{
+	char *data = NULL;
+	int dsize = 0;
+	char *xcap_uri;
+	int res = RES_OK;
+	
+	xcap_uri = xcap_uri_for_msg_rules(xcap_root, uri);
+	res = xcap_query(xcap_uri, xcap_params, &data, &dsize);
+	if (res != RES_OK) {
+		TRACE_LOG("XCAP problems for uri \'%s\'\n", xcap_uri ? xcap_uri: "???");
+		if (data) cds_free(data);
+		if (xcap_uri) cds_free(xcap_uri);
+		return RES_XCAP_QUERY_ERR;
+	}
+	if (xcap_uri) cds_free(xcap_uri);
+	
+	/* parse input data */
+	res = parse_msg_rules(data, dsize, dst);
+	if (res != RES_OK) {
+		ERROR_LOG("Error occured during document parsing!\n");
+	}
+
+	if (data) cds_free(data);
+	return res;
+}
+
+int get_msg_rules_action(cp_ruleset_t *r, const str_t *wuri, 
+		msg_handling_t *dst_action)
+{
+	int res = 1; /* rule not found */
+	cp_rule_t *rule;
+	msg_handling_t a = msg_handling_block;
+	msg_handling_t aa;
+	
+	if (!r) return -1;
+	
+	rule = r->rules;
+	while (rule) {
+		DEBUG_LOG("TRYING rule %.*s for uri %.*s\n", 
+					FMT_STR(rule->id), FMT_STR(*wuri));
+		if (is_rule_for_uri(rule, wuri)) {
+			DEBUG_LOG("rule %.*s matches for uri %.*s\n", 
+					FMT_STR(rule->id), FMT_STR(*wuri));
+
+			if (!rule->actions) continue;
+			if (!rule->actions->unknown) continue;
+			aa = *(msg_handling_t*)(rule->actions->unknown->data);
+			if (aa > a) a = aa;
+			res = 0;
+		}
+		rule = rule->next;
+	}
+	if (dst_action && (res == 0)) *dst_action = a;
+	
+	return res;
+}
+
+void free_msg_actions(cp_actions_t *a)
+{
+	cp_unknown_t *u, *nu;
+	
+	if (!a) return;
+	
+	u = a->unknown;
+	while (u) {
+		nu = u->next;
+		cds_free(u);
+		u = nu;
+	}
+	cds_free(a);
+}
+
+void free_msg_rules(cp_ruleset_t *r)
+{
+	free_common_rules(r, free_msg_actions);
+}
+

+ 50 - 0
lib/xcap/msg_rules.h

@@ -0,0 +1,50 @@
+/* 
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MSG_RULES_H
+#define __MSG_RULES_H
+
+#include <cds/sstr.h>
+#include <xcap/xcap_client.h>
+#include <xcap/common_policy.h>
+
+typedef cp_ruleset_t msg_rules_t;
+
+/* Type defining action for pres_rules */
+typedef enum {
+	msg_handling_block,
+/*	msg_handling_confirm, */
+	msg_handling_allow
+} msg_handling_t;
+
+char *xcap_uri_for_msg_rules(const char *xcap_root, const str_t *uri);
+int get_msg_rules(const char *xcap_root, const str_t *uri, xcap_query_params_t *xcap_params, msg_rules_t **dst);
+void free_msg_rules(cp_ruleset_t *r);
+void free_msg_actions(cp_actions_t *a);
+
+/* returns 0 if rule found, 1 if not found and -1 on error */
+int get_msg_rules_action(msg_rules_t *r, const str_t *wuri, msg_handling_t *dst_action);
+
+#endif

+ 340 - 0
lib/xcap/parse_common_rules.c

@@ -0,0 +1,340 @@
+/* 
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <xcap/parse_common_rules.h>
+#include <xcap/xcap_result_codes.h>
+
+#include <cds/dstring.h>
+#include <cds/memory.h>
+#include <cds/logger.h>
+#include <cds/list.h>
+#include <string.h>
+
+#include <xcap/xml_utils.h>
+
+char *common_policy_ns = NULL;
+
+static int read_sphere(xmlNode *n, cp_sphere_t **dst)
+{
+	*dst = (cp_sphere_t*)cds_malloc(sizeof(cp_sphere_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	(*dst)->next = NULL;
+	
+	str_dup_zt(&(*dst)->value, get_node_value(n));
+	return RES_OK;
+}
+
+static int read_validity(xmlNode *n, cp_validity_t **dst)
+{
+	const char *from, *to;
+	*dst = (cp_validity_t*)cds_malloc(sizeof(cp_validity_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	
+	from = get_node_value(find_node(n, "from", common_policy_ns));
+	to = get_node_value(find_node(n, "to", common_policy_ns));
+	
+	(*dst)->from = xmltime2time(from);
+	(*dst)->to = xmltime2time(to);
+	return RES_OK;
+}
+
+static int read_id(xmlNode *n, cp_id_t **dst)
+{
+	*dst = (cp_id_t*)cds_malloc(sizeof(cp_id_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	(*dst)->next = NULL;
+	
+	get_str_attr(n, "entity", &(*dst)->entity);
+	if ((*dst)->entity.len == 0) {
+		/* hack - eyeBeams format differs from draft ! */
+		str_dup_zt(&(*dst)->entity, get_node_value(n));
+	}
+
+	return RES_OK;
+}
+
+static int read_domain(xmlNode *n, cp_domain_t **dst)
+{
+	*dst = (cp_domain_t*)cds_malloc(sizeof(cp_domain_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	(*dst)->next = NULL;
+	
+	get_str_attr(n, "domain", &(*dst)->domain);
+	return RES_OK;
+}
+
+static int read_except(xmlNode *n, cp_except_t **dst)
+{
+	*dst = (cp_except_t*)cds_malloc(sizeof(cp_except_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	(*dst)->next = NULL;
+	
+	get_str_attr(n, "entity", &(*dst)->entity);
+	return RES_OK;
+}
+
+static int read_except_domain(xmlNode *n, cp_except_domain_t **dst)
+{
+	*dst = (cp_except_domain_t*)cds_malloc(sizeof(cp_except_domain_t));
+	if (!*dst) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	(*dst)->next = NULL;
+	
+	get_str_attr(n, "domain", &(*dst)->domain);
+	return RES_OK;
+}
+
+static int read_any_identity(xmlNode *an, cp_any_identity_t **dst)
+{
+	cp_domain_t *domain, *last_domain = NULL;
+	cp_except_domain_t *except, *last_except = NULL;
+	xmlNode *n;
+	int res = RES_OK;
+	
+	*dst = (cp_any_identity_t*)cds_malloc(sizeof(cp_any_identity_t));
+	if (!*dst) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+	
+	n = an->children;
+	while (n) {
+		if (n->type == XML_ELEMENT_NODE) {
+			if (cmp_node(n, "domain", common_policy_ns) >= 0) {
+				res = read_domain(n, &domain);
+				if (res != 0) break;
+				LINKED_LIST_ADD((*dst)->domains, last_domain, domain);
+			}
+			else if (cmp_node(n, "except-domain", common_policy_ns) >= 0) {
+				res = read_except_domain(n, &except);
+				if (res != 0) break;
+				LINKED_LIST_ADD((*dst)->except_domains, last_except, except);
+			}
+		}
+		
+		n = n->next;
+	}
+	return res;
+}
+
+static int read_identity(xmlNode *idn, cp_identity_t **dst)
+{
+	cp_id_t *id, *last_id = NULL;
+	cp_domain_t *domain, *last_domain = NULL;
+	cp_except_t *except, *last_except = NULL;
+	xmlNode *n;
+	int res = RES_OK;
+	
+	*dst = (cp_identity_t*)cds_malloc(sizeof(cp_identity_t));
+	if (!*dst) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(**dst));
+
+	n = idn->children;
+	while (n) {
+		if (n->type == XML_ELEMENT_NODE) {
+			if (cmp_node(n, "id", common_policy_ns) >= 0) {
+				res = read_id(n, &id);
+				if (res != 0) break;
+				LINKED_LIST_ADD((*dst)->ids, last_id, id);
+			}
+			else if (cmp_node(n, "domain", common_policy_ns) >= 0) {
+				res = read_domain(n, &domain);
+				if (res != 0) break;
+				LINKED_LIST_ADD((*dst)->domains, last_domain, domain);
+			}
+			else if (cmp_node(n, "except", common_policy_ns) >= 0) {
+				res = read_except(n, &except);
+				if (res != 0) break;
+				LINKED_LIST_ADD((*dst)->excepts, last_except, except);
+			}
+			else if (cmp_node(n, "any-identity", common_policy_ns) >= 0) {
+				res = read_any_identity(n, &(*dst)->any_identity);
+				if (res != 0) break;
+			}
+		}
+		
+		n = n->next;
+	}
+	
+	return res;
+}
+
+static int read_conditions(xmlNode *cn, cp_conditions_t **dst)
+{
+	xmlNode *n;
+	int res = RES_OK;
+	cp_sphere_t *sphere, * last_sphere = NULL;
+	if ((!cn) || (!dst)) return RES_INTERNAL_ERR;
+	
+	*dst = (cp_conditions_t*)cds_malloc(sizeof(cp_conditions_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(cp_conditions_t));
+	
+	n = cn->children;
+	while (n) {
+		if (n->type == XML_ELEMENT_NODE) {
+			if (cmp_node(n, "validity", common_policy_ns) >= 0) {
+				/* FIXME: free existing validity */
+				res = read_validity(n, &(*dst)->validity);
+				if (res != 0) break;
+			}
+			else {
+				if (cmp_node(n, "identity", common_policy_ns) >= 0) {
+					/* FIXME: free existing identity */
+					res = read_identity(n, &(*dst)->identity);
+					if (res != 0) break;
+				}
+				else {
+					if (cmp_node(n, "sphere", common_policy_ns) >= 0) {
+						res = read_sphere(n, &sphere);
+						if (res != 0) break;
+						LINKED_LIST_ADD((*dst)->spheres, last_sphere, sphere);
+					}
+					/* else process other elements ? */
+				}
+				
+			}
+		}
+		n = n->next;
+	}
+
+	return res;
+}
+
+static int read_transformations(xmlNode *tn, cp_transformations_t **dst)
+{
+	int res = RES_OK;
+	if ((!tn) || (!dst)) return RES_INTERNAL_ERR;
+	
+	*dst = (cp_transformations_t*)cds_malloc(sizeof(cp_transformations_t));
+	if (!*dst) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(cp_transformations_t));
+
+	DEBUG_LOG("transformations for pres_rules not used\n");
+
+	return res;
+}
+
+static int read_rule(xmlNode *rn, cp_rule_t **dst, 
+		cp_read_actions_func read_actions,
+		cp_free_actions_func free_actions)
+{
+	xmlNode *n;
+	int res = RES_OK;
+	if ((!rn) || (!dst)) return RES_INTERNAL_ERR;
+	
+	*dst = (cp_rule_t*)cds_malloc(sizeof(cp_rule_t));
+	if (!*dst) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(cp_rule_t));
+
+	get_str_attr(rn, "id", &(*dst)->id);
+
+	n = find_node(rn, "actions", common_policy_ns);
+	if (n && (res == 0) && read_actions) res = read_actions(n, &(*dst)->actions);
+	
+	n = find_node(rn, "conditions", common_policy_ns);
+	if (n && (res == 0)) res = read_conditions(n, &(*dst)->conditions);
+	
+	n = find_node(rn, "transformations", common_policy_ns);
+	if (n && (res == 0)) res = read_transformations(n, &(*dst)->transformations);
+	
+	if (res != 0) {
+		free_cp_rule(*dst, free_actions);
+		*dst = NULL;
+		return res;
+	}
+
+	return 0;
+}
+
+static int read_common_rules(xmlNode *root, cp_ruleset_t **dst, 
+		cp_read_actions_func read_actions, cp_free_actions_func free_actions)
+{
+	cp_ruleset_t *rs = NULL;
+	cp_rule_t *r, *last = NULL;
+	xmlNode *n;
+	int res = RES_OK;
+	
+	if (!dst) return RES_INTERNAL_ERR;
+	else *dst = NULL;
+	if (!root) return RES_INTERNAL_ERR;
+	
+	if (cmp_node(root, "ruleset", common_policy_ns) < 0) {
+		ERROR_LOG("document is not a ruleset \n");
+		return RES_INTERNAL_ERR;
+	}
+
+	rs = (cp_ruleset_t*)cds_malloc(sizeof(cp_ruleset_t));
+	if (!rs) return RES_MEMORY_ERR;
+	*dst = rs;
+	memset(rs, 0, sizeof(*rs));
+
+	
+	/* read rules in ruleset */
+	n = root->children;
+	while (n) {
+		if (n->type == XML_ELEMENT_NODE) {
+			if (cmp_node(n, "rule", common_policy_ns) >= 0) {
+				res = read_rule(n, &r, read_actions, free_actions);
+				if (res == 0) {
+					if (r) LINKED_LIST_ADD(rs->rules, last, r);
+				}
+				else break;
+			}
+		}
+		n = n->next;
+	}
+
+	return res;
+}
+
+int parse_common_rules(const char *data, int dsize, cp_ruleset_t **dst,
+	cp_read_actions_func read_actions, cp_free_actions_func free_actions)
+{
+	int res = 0;
+	xmlDocPtr doc; /* the resulting document tree */
+
+	if (dst) *dst = NULL;
+	doc = xmlReadMemory(data, dsize, NULL, NULL, xml_parser_flags);
+	if (doc == NULL) {
+		ERROR_LOG("can't parse document\n");
+		return RES_INTERNAL_ERR;
+	}
+	
+	res = read_common_rules(xmlDocGetRootElement(doc), dst, 
+			read_actions, free_actions);
+	if ((res != RES_OK) && (dst)) {
+		/* may be set => must be freed */
+		free_common_rules(*dst, free_actions);
+		*dst = NULL;
+	}
+
+	xmlFreeDoc(doc);
+	return res;
+}
+

+ 40 - 0
lib/xcap/parse_common_rules.h

@@ -0,0 +1,40 @@
+/* 
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __PARSE_COMMON_RULES_H
+#define __PARSE_COMMON_RULES_H
+
+#include <xcap/pres_rules.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+typedef int(cp_read_actions_func)(xmlNode *an, cp_actions_t **dst);
+
+int parse_common_rules(const char *data, int dsize, cp_ruleset_t **dst,
+	cp_read_actions_func read_actions, cp_free_actions_func free_actions);
+
+/* extern char *common_policy_ns; */
+
+#endif

+ 92 - 0
lib/xcap/parse_msg_rules.c

@@ -0,0 +1,92 @@
+/* 
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <xcap/parse_common_rules.h>
+#include <xcap/parse_msg_rules.h>
+#include <xcap/xcap_result_codes.h>
+
+#include <cds/dstring.h>
+#include <cds/memory.h>
+#include <cds/logger.h>
+#include <cds/list.h>
+#include <string.h>
+
+#include <xcap/xml_utils.h>
+
+char *msg_rules_ns = NULL;
+
+static int str2msg_handling(const char *s, msg_handling_t *dst)
+{
+	if (!s) return RES_INTERNAL_ERR;
+	
+	if (strcmp(s, "allow") == 0) {
+		*dst = msg_handling_allow;
+		return 0;
+	}
+	if (strcmp(s, "block") == 0) {
+		*dst = msg_handling_block;
+		return 0;
+	}
+/*	if (strcmp(s, "polite-block") == 0) {
+		*dst = msg_handling_polite_block;
+		return 0;
+	}
+	if (strcmp(s, "confirm") == 0) {
+		*dst = msg_handling_confirm;
+		return 0;
+	}*/
+	ERROR_LOG("invalid im-handling value: \'%s\'\n", s);
+	return RES_INTERNAL_ERR;
+}
+
+static int read_msg_actions(xmlNode *an, cp_actions_t **dst)
+{
+	xmlNode *n;
+	const char *s;
+	int res = RES_OK;
+	if ((!an) || (!dst)) return RES_INTERNAL_ERR;
+	
+	*dst = (cp_actions_t*)cds_malloc(sizeof(cp_actions_t));
+	if (!(*dst)) return RES_MEMORY_ERR;
+	memset(*dst, 0, sizeof(cp_actions_t));
+
+	n = find_node(an, "im-handling", msg_rules_ns);
+	if (n) {
+		/* may be only one sub-handling node? */
+		s = get_node_value(n);
+		(*dst)->unknown = create_unknown(sizeof(msg_handling_t));
+		if (!(*dst)->unknown) return RES_MEMORY_ERR;
+		res = str2msg_handling(s, (msg_handling_t*)(*dst)->unknown->data);
+	}
+
+	return res;
+}
+
+int parse_msg_rules(const char *data, int dsize, cp_ruleset_t **dst)
+{
+	return parse_common_rules(data, dsize, dst, 
+			read_msg_actions, free_msg_actions);
+}
+

+ 34 - 0
lib/xcap/parse_msg_rules.h

@@ -0,0 +1,34 @@
+/* 
+ * Copyright (C) 2005 iptelorg GmbH
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __PARSE_MSG_RULES_H
+#define __PARSE_MSG_RULES_H
+
+#include <xcap/msg_rules.h>
+#include <xcap/parse_common_rules.h>
+
+int parse_msg_rules(const char *data, int dsize, cp_ruleset_t **dst);
+
+#endif

+ 2 - 302
lib/xcap/parse_pres_rules.c

@@ -34,16 +34,8 @@
 
 #include <xcap/xml_utils.h>
 
-char *common_policy_ns = NULL;
 char *pres_rules_ns = NULL;
 
-static cp_unknown_t *create_unknown(int data_size)
-{
-	cp_unknown_t *u = cds_malloc(sizeof(cp_unknown_t) + data_size);
-	u->next = NULL;
-	return u;
-}
-
 static int str2sub_handling(const char *s, sub_handling_t *dst)
 {
 	if (!s) return RES_INTERNAL_ERR;
@@ -68,7 +60,7 @@ static int str2sub_handling(const char *s, sub_handling_t *dst)
 	return RES_INTERNAL_ERR;
 }
 
-static int read_actions(xmlNode *an, cp_actions_t **dst)
+static int read_pres_actions(xmlNode *an, cp_actions_t **dst)
 {
 	xmlNode *n;
 	const char *s;
@@ -91,300 +83,8 @@ static int read_actions(xmlNode *an, cp_actions_t **dst)
 	return res;
 }
 
-static int read_sphere(xmlNode *n, cp_sphere_t **dst)
-{
-	*dst = (cp_sphere_t*)cds_malloc(sizeof(cp_sphere_t));
-	if (!(*dst)) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	(*dst)->next = NULL;
-	
-	str_dup_zt(&(*dst)->value, get_node_value(n));
-	return RES_OK;
-}
-
-static int read_validity(xmlNode *n, cp_validity_t **dst)
-{
-	const char *from, *to;
-	*dst = (cp_validity_t*)cds_malloc(sizeof(cp_validity_t));
-	if (!(*dst)) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	
-	from = get_node_value(find_node(n, "from", common_policy_ns));
-	to = get_node_value(find_node(n, "to", common_policy_ns));
-	
-	(*dst)->from = xmltime2time(from);
-	(*dst)->to = xmltime2time(to);
-	return RES_OK;
-}
-
-static int read_id(xmlNode *n, cp_id_t **dst)
-{
-	*dst = (cp_id_t*)cds_malloc(sizeof(cp_id_t));
-	if (!(*dst)) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	(*dst)->next = NULL;
-	
-	get_str_attr(n, "entity", &(*dst)->entity);
-	if ((*dst)->entity.len == 0) {
-		/* hack - eyeBeams format differs from draft ! */
-		str_dup_zt(&(*dst)->entity, get_node_value(n));
-	}
-
-	return RES_OK;
-}
-
-static int read_domain(xmlNode *n, cp_domain_t **dst)
-{
-	*dst = (cp_domain_t*)cds_malloc(sizeof(cp_domain_t));
-	if (!(*dst)) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	(*dst)->next = NULL;
-	
-	get_str_attr(n, "domain", &(*dst)->domain);
-	return RES_OK;
-}
-
-static int read_except(xmlNode *n, cp_except_t **dst)
-{
-	*dst = (cp_except_t*)cds_malloc(sizeof(cp_except_t));
-	if (!(*dst)) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	(*dst)->next = NULL;
-	
-	get_str_attr(n, "entity", &(*dst)->entity);
-	return RES_OK;
-}
-
-static int read_except_domain(xmlNode *n, cp_except_domain_t **dst)
-{
-	*dst = (cp_except_domain_t*)cds_malloc(sizeof(cp_except_domain_t));
-	if (!*dst) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	(*dst)->next = NULL;
-	
-	get_str_attr(n, "domain", &(*dst)->domain);
-	return RES_OK;
-}
-
-static int read_any_identity(xmlNode *an, cp_any_identity_t **dst)
-{
-	cp_domain_t *domain, *last_domain = NULL;
-	cp_except_domain_t *except, *last_except = NULL;
-	xmlNode *n;
-	int res = RES_OK;
-	
-	*dst = (cp_any_identity_t*)cds_malloc(sizeof(cp_any_identity_t));
-	if (!*dst) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-	
-	n = an->children;
-	while (n) {
-		if (n->type == XML_ELEMENT_NODE) {
-			if (cmp_node(n, "domain", common_policy_ns) >= 0) {
-				res = read_domain(n, &domain);
-				if (res != 0) break;
-				LINKED_LIST_ADD((*dst)->domains, last_domain, domain);
-			}
-			else if (cmp_node(n, "except-domain", common_policy_ns) >= 0) {
-				res = read_except_domain(n, &except);
-				if (res != 0) break;
-				LINKED_LIST_ADD((*dst)->except_domains, last_except, except);
-			}
-		}
-		
-		n = n->next;
-	}
-	return res;
-}
-
-static int read_identity(xmlNode *idn, cp_identity_t **dst)
-{
-	cp_id_t *id, *last_id = NULL;
-	cp_domain_t *domain, *last_domain = NULL;
-	cp_except_t *except, *last_except = NULL;
-	xmlNode *n;
-	int res = RES_OK;
-	
-	*dst = (cp_identity_t*)cds_malloc(sizeof(cp_identity_t));
-	if (!*dst) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(**dst));
-
-	n = idn->children;
-	while (n) {
-		if (n->type == XML_ELEMENT_NODE) {
-			if (cmp_node(n, "id", common_policy_ns) >= 0) {
-				res = read_id(n, &id);
-				if (res != 0) break;
-				LINKED_LIST_ADD((*dst)->ids, last_id, id);
-			}
-			else if (cmp_node(n, "domain", common_policy_ns) >= 0) {
-				res = read_domain(n, &domain);
-				if (res != 0) break;
-				LINKED_LIST_ADD((*dst)->domains, last_domain, domain);
-			}
-			else if (cmp_node(n, "except", common_policy_ns) >= 0) {
-				res = read_except(n, &except);
-				if (res != 0) break;
-				LINKED_LIST_ADD((*dst)->excepts, last_except, except);
-			}
-			else if (cmp_node(n, "any-identity", common_policy_ns) >= 0) {
-				res = read_any_identity(n, &(*dst)->any_identity);
-				if (res != 0) break;
-			}
-		}
-		
-		n = n->next;
-	}
-	
-	return res;
-}
-
-static int read_conditions(xmlNode *cn, cp_conditions_t **dst)
-{
-	xmlNode *n;
-	int res = RES_OK;
-	cp_sphere_t *sphere, * last_sphere = NULL;
-	if ((!cn) || (!dst)) return RES_INTERNAL_ERR;
-	
-	*dst = (cp_conditions_t*)cds_malloc(sizeof(cp_conditions_t));
-	if (!(*dst)) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(cp_conditions_t));
-	
-	n = cn->children;
-	while (n) {
-		if (n->type == XML_ELEMENT_NODE) {
-			if (cmp_node(n, "validity", common_policy_ns) >= 0) {
-				/* FIXME: free existing validity */
-				res = read_validity(n, &(*dst)->validity);
-				if (res != 0) break;
-			}
-			else {
-				if (cmp_node(n, "identity", common_policy_ns) >= 0) {
-					/* FIXME: free existing identity */
-					res = read_identity(n, &(*dst)->identity);
-					if (res != 0) break;
-				}
-				else {
-					if (cmp_node(n, "sphere", common_policy_ns) >= 0) {
-						res = read_sphere(n, &sphere);
-						if (res != 0) break;
-						LINKED_LIST_ADD((*dst)->spheres, last_sphere, sphere);
-					}
-					/* else process other elements ? */
-				}
-				
-			}
-		}
-		n = n->next;
-	}
-
-	return res;
-}
-
-static int read_transformations(xmlNode *tn, cp_transformations_t **dst)
-{
-	int res = RES_OK;
-	if ((!tn) || (!dst)) return RES_INTERNAL_ERR;
-	
-	*dst = (cp_transformations_t*)cds_malloc(sizeof(cp_transformations_t));
-	if (!*dst) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(cp_transformations_t));
-
-	DEBUG_LOG("transformations for pres_rules not used\n");
-
-	return res;
-}
-
-static int read_rule(xmlNode *rn, cp_rule_t **dst)
-{
-	xmlNode *n;
-	int res = RES_OK;
-	if ((!rn) || (!dst)) return RES_INTERNAL_ERR;
-	
-	*dst = (cp_rule_t*)cds_malloc(sizeof(cp_rule_t));
-	if (!*dst) return RES_MEMORY_ERR;
-	memset(*dst, 0, sizeof(cp_rule_t));
-
-	get_str_attr(rn, "id", &(*dst)->id);
-
-	n = find_node(rn, "actions", common_policy_ns);
-	if (n && (res == 0)) res = read_actions(n, &(*dst)->actions);
-	
-	n = find_node(rn, "conditions", common_policy_ns);
-	if (n && (res == 0)) res = read_conditions(n, &(*dst)->conditions);
-	
-	n = find_node(rn, "transformations", common_policy_ns);
-	if (n && (res == 0)) res = read_transformations(n, &(*dst)->transformations);
-	
-	if (res != 0) {
-		free_rule(*dst);
-		*dst = NULL;
-		return res;
-	}
-
-	return 0;
-}
-
-static int read_pres_rules(xmlNode *root, cp_ruleset_t **dst)
-{
-	cp_ruleset_t *rs = NULL;
-	cp_rule_t *r, *last = NULL;
-	xmlNode *n;
-	int res = RES_OK;
-	
-	if (!dst) return RES_INTERNAL_ERR;
-	else *dst = NULL;
-	if (!root) return RES_INTERNAL_ERR;
-	
-	if (cmp_node(root, "ruleset", common_policy_ns) < 0) {
-		ERROR_LOG("document is not a ruleset \n");
-		return RES_INTERNAL_ERR;
-	}
-
-	rs = (cp_ruleset_t*)cds_malloc(sizeof(cp_ruleset_t));
-	if (!rs) return RES_MEMORY_ERR;
-	*dst = rs;
-	memset(rs, 0, sizeof(*rs));
-
-	
-	/* read rules in ruleset */
-	n = root->children;
-	while (n) {
-		if (n->type == XML_ELEMENT_NODE) {
-			if (cmp_node(n, "rule", common_policy_ns) >= 0) {
-				res = read_rule(n, &r);
-				if (res == 0) {
-					if (r) LINKED_LIST_ADD(rs->rules, last, r);
-				}
-				else break;
-			}
-		}
-		n = n->next;
-	}
-
-	return res;
-}
-
 int parse_pres_rules(const char *data, int dsize, cp_ruleset_t **dst)
 {
-	int res = 0;
-	xmlDocPtr doc; /* the resulting document tree */
-
-	if (dst) *dst = NULL;
-	doc = xmlReadMemory(data, dsize, NULL, NULL, xml_parser_flags);
-	if (doc == NULL) {
-		ERROR_LOG("can't parse document\n");
-		return RES_INTERNAL_ERR;
-	}
-	
-	res = read_pres_rules(xmlDocGetRootElement(doc), dst);
-	if ((res != RES_OK) && (dst)) {
-		/* may be set => must be freed */
-		free_pres_rules(*dst);
-		*dst = NULL;
-	}
-
-	xmlFreeDoc(doc);
-	return res;
+	return parse_common_rules(data, dsize, dst, read_pres_actions, free_pres_actions);
 }
 

+ 1 - 0
lib/xcap/parse_pres_rules.h

@@ -27,6 +27,7 @@
 #define __PARSE_PRES_RULES_H
 
 #include <xcap/pres_rules.h>
+#include <xcap/parse_common_rules.h>
 
 int parse_pres_rules(const char *data, int dsize, cp_ruleset_t **dst);
 

+ 2 - 207
lib/xcap/pres_rules.c

@@ -87,107 +87,6 @@ int get_pres_rules(const char *xcap_root, const str_t *uri, xcap_query_params_t
 	return res;
 }
 
-static void parse_uri(const str_t *uri, str_t *user, str_t *domain)
-{
-	char *a;
-	char *d;
-	str_t s;
-	
-	str_clear(user);
-	str_clear(domain);
-	if (uri->len > 0) {
-		d = str_strchr(uri, ':');
-		if (d) {
-			s.s = d + 1;
-			s.len = uri->len - (s.s - uri->s);
-		}
-		else s = *uri;
-		a = str_strchr(&s, '@');
-		if (a) {
-			user->s = s.s;
-			user->len = a - s.s;
-		}
-		domain->s = s.s + user->len;
-		if (a) domain->s++;
-		domain->len = uri->len - (domain->s - uri->s);
-		
-/*		TRACE_LOG("parse uri \'%.*s\': user=\'%.*s\' domain=\'%.*s\'\n",
-				FMT_STR(*uri), FMT_STR(*user), FMT_STR(*domain));*/
-	}
-}
-
-/* returns 1 if rule is used for uri */
-int is_rule_for_uri(cp_rule_t *rule, const str_t *uri)
-{	
-	cp_identity_t *id;
-	int ok = 0;
-	str_t domain, user;
-	str_t d_, u_;
-	cp_domain_t *d;
-	cp_id_t *i;
-	cp_except_t *e;
-	cp_except_domain_t *ed;
-	
-	if (!rule) return 0;
-	if (!rule->conditions) return 1; /* FIXME: ??? */
-	id = rule->conditions->identity;
-	if (!id) return 0;
-	
-	parse_uri(uri, &user, &domain);
-	
-	i = id->ids;
-	while (i) {
-		parse_uri(&i->entity, &u_, &d_);
-/*		TRACE_LOG("comparing uris \'%.*s\' \'%.*s\' "
-				"domains \'%.*s\' \'%.*s\'\n", 
-				FMT_STR(user), FMT_STR(u_),
-				FMT_STR(domain), FMT_STR(d_));*/
-		if (str_case_equals(&user, &u_) == 0) {
-			if (str_nocase_equals(&domain, &d_) == 0) {
-/*				TRACE_LOG("id found\n");*/
-				return 1;
-			}
-		}
-		i = i->next;
-	}
-	
-	d = id->domains;
-	while (d) {
-/*		TRACE_LOG("comparing domains \'%.*s\' \'%.*s\'\n",
-				FMT_STR(domain), FMT_STR(d->domain));*/
-		if (str_nocase_equals(&domain, &d->domain) == 0) ok = 1;
-		d = d->next;
-	}
-	if (ok) {
-		e = id->excepts;
-		while (e) {
-			if (str_case_equals(&user, &e->entity) == 0)
-				return 0; /* excepts matched */
-			e = e->next;
-		}
-/*		TRACE_LOG("domain found and excepts not matched\n");*/
-		return 1;
-	}
-
-	if (id->any_identity) {
-		d = id->any_identity->domains;
-		while (d) {
-			if (str_nocase_equals(&domain, &d->domain) == 0) {
-/*				TRACE_LOG("domain matches for anonymous\n");*/
-				return 1;
-			}
-			d = d->next;
-		}
-		
-		ed = id->any_identity->except_domains;
-		while (ed) {
-			if (str_nocase_equals(&domain, &d->domain) == 0) return 0;
-			ed = ed->next;
-		}
-	}
-	return 0;
-}
-
 int get_pres_rules_action(cp_ruleset_t *r, const str_t *wuri, 
 		sub_handling_t *dst_action)
 {
@@ -221,77 +120,7 @@ int get_pres_rules_action(cp_ruleset_t *r, const str_t *wuri,
 
 /* ------- freeing used memory for pres-rules ------- */
 
-static void free_identity(cp_identity_t *id)
-{
-	cp_id_t *i, *ni;
-	cp_domain_t *d, *nd;
-	cp_except_t *e, *ne;
-	cp_except_domain_t *ed, *ned;
-	
-	if (!id) return;
-	
-	i = id->ids;
-	while (i) {
-		ni = i->next;
-		str_free_content(&i->entity);
-		cds_free(i);
-		i = ni;
-	}
-	
-	d = id->domains;
-	while (d) {
-		nd = d->next;
-		str_free_content(&d->domain);
-		cds_free(d);
-		d = nd;
-	}
-	
-	e = id->excepts;
-	while (e) {
-		ne = e->next;
-		str_free_content(&e->entity);
-		cds_free(e);
-		e = ne;
-	}
-
-	if (id->any_identity) {
-		d = id->any_identity->domains;
-		while (d) {
-			nd = d->next;
-			str_free_content(&d->domain);
-			cds_free(d);
-			d = nd;
-		}
-		
-		ed = id->any_identity->except_domains;
-		while (ed) {
-			ned = ed->next;
-			str_free_content(&ed->domain);
-			cds_free(ed);
-			ed = ned;
-		}
-	}
-	
-	cds_free(id);
-}
-
-static void free_conditions(cp_conditions_t *c)
-{
-	cp_sphere_t *s, *n;
-	if (!c) return;
-	if (c->validity) cds_free(c->validity);
-	if (c->identity) free_identity(c->identity);
-	s = c->spheres;
-	while (s) {
-		n = s->next;
-		str_free_content(&s->value);
-		cds_free(s);
-		s = n;
-	}
-	cds_free(c);
-}
-
-static void free_actions(cp_actions_t *a)
+void free_pres_actions(cp_actions_t *a)
 {
 	cp_unknown_t *u, *nu;
 	
@@ -306,42 +135,8 @@ static void free_actions(cp_actions_t *a)
 	cds_free(a);
 }
 
-static void free_transformations(cp_transformations_t *t)
-{
-	cp_unknown_t *u, *nu;
-	
-	if (!t) return;
-	
-	u = t->unknown;
-	while (u) {
-		nu = u->next;
-		cds_free(u);
-		u = nu;
-	}
-	cds_free(t);
-}
-
-void free_rule(cp_rule_t *r)
-{
-	if (!r) return;
-	if (r->conditions) free_conditions(r->conditions);
-	if (r->actions) free_actions(r->actions);
-	if (r->transformations) free_transformations(r->transformations);
-	str_free_content(&r->id);
-	cds_free(r);
-}
-
 void free_pres_rules(cp_ruleset_t *r)
 {
-	cp_rule_t *rule, *n;
-	
-	if (!r) return;
-	rule = r->rules;
-	while (rule) {
-		n = rule->next;
-		free_rule(rule);
-		rule = n;
-	}
-	cds_free(r);
+	free_common_rules(r, free_pres_actions);
 }
 

+ 1 - 1
lib/xcap/pres_rules.h

@@ -43,7 +43,7 @@ typedef enum {
 char *xcap_uri_for_pres_rules(const char *xcap_root, const str_t *uri);
 int get_pres_rules(const char *xcap_root, const str_t *uri, xcap_query_params_t *xcap_params, cp_ruleset_t **dst);
 void free_pres_rules(cp_ruleset_t *r);
-void free_rule(cp_rule_t *r);
+void free_pres_actions(cp_actions_t *a);
 
 /* returns 0 if rule found, 1 if not found and -1 on error */
 int get_pres_rules_action(cp_ruleset_t *r, const str_t *wuri, sub_handling_t *dst_action);

+ 1 - 1
lib/xcap/xcap_client.c

@@ -78,7 +78,7 @@ int xcap_query(const char *uri, xcap_query_params_t *params, char **buf, int *bs
 	if (!handle) handle = curl_easy_init(); /*FIXME: experimental*/
 	if (handle) {
 		curl_easy_setopt(handle, CURLOPT_URL, uri);
-		TRACE_LOG("uri: %s\n", uri ? uri : "<null>");
+		/* TRACE_LOG("uri: %s\n", uri ? uri : "<null>"); */
 		
 		/* do not store data into a file - store them in memory */
 		curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data_func);