4 * Copyright (C) 2006 Voice Sistem S.R.L.
6 * This file is part of Kamailio, a free SIP server.
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * \brief Kamailio Presence_XML :: Notify BODY handling
25 * \ingroup presence_xml
31 #include <libxml/parser.h>
33 #include "../../core/mem/mem.h"
34 #include "../presence/utils_func.h"
35 #include "../presence/hash.h"
36 #include "xcap_auth.h"
38 #include "notify_body.h"
39 #include "presence_xml.h"
41 extern int pxml_force_dummy_presence;
42 extern int pxml_force_single_body;
43 extern str pxml_single_body_priorities;
44 extern str pxml_single_body_lookup_element;
46 str *offline_nbody(str *body);
47 str *agregate_xmls(str *pres_user, str *pres_domain, str **body_array, int n);
48 str *agregate_xmls_priority(str *pres_user, str *pres_domain, str **body_array, int n);
49 str *get_final_notify_body(
50 subs_t *subs, str *notify_body, xmlNodePtr rule_node);
52 void free_xml_body(char *body)
61 #define PRESENCE_EMPTY_BODY_SIZE 1024
63 #define PRESENCE_EMPTY_BODY \
64 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
65 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\
66 xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\"\
67 xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\"\
68 xmlns:c=\"urn:ietf:params:xml:ns:pidf:cipid\" entity=\"%.*s\">\
69 <tuple xmlns=\"urn:ietf:params:xml:ns:pidf\" id=\"615293b33c62dec073e05d9421e9f48b\">\
74 <note xmlns=\"urn:ietf:params:xml:ns:pidf\">Available</note>\
75 <dm:person xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\"\
76 xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" id=\"1\">\
78 <dm:note>Available</dm:note>\
82 str *pres_agg_nbody_empty(str *pres_user, str *pres_domain)
89 LM_DBG("creating empty presence for [pres_user]=%.*s [pres_domain]= %.*s\n",
90 pres_user->len, pres_user->s, pres_domain->len, pres_domain->s);
92 if(pres_user->len + sizeof(PRESENCE_EMPTY_BODY)
93 >= PRESENCE_EMPTY_BODY_SIZE - 1) {
94 LM_ERR("insufficient buffer to add user (its len is: %d)\n",
98 body_array = (str *)pkg_malloc(sizeof(str));
99 if(body_array == NULL) {
100 LM_ERR("no more pkg\n");
104 body = (char *)pkg_malloc(PRESENCE_EMPTY_BODY_SIZE);
105 if(body_array == NULL) {
106 LM_ERR("no more pkg\n");
107 pkg_free(body_array);
110 snprintf(body, PRESENCE_EMPTY_BODY_SIZE, PRESENCE_EMPTY_BODY,
111 pres_user->len, pres_user->s);
112 body_array->s = body;
113 body_array->len = strlen(body);
116 n_body = agregate_xmls(pres_user, pres_domain, &body_array, 1);
117 LM_DBG("[n_body]=%p\n", n_body);
119 LM_DBG("[*n_body]=%.*s\n", n_body->len, n_body->s);
122 LM_ERR("while aggregating body for: %.*s\n", pres_user->len,
127 pkg_free(body_array);
136 str *pres_agg_nbody(str *pres_user, str *pres_domain, str **body_array, int n,
142 if(body_array == NULL && (!pxml_force_dummy_presence))
145 if(body_array == NULL)
146 return pres_agg_nbody_empty(pres_user, pres_domain);
149 body = body_array[off_index];
150 body_array[off_index] = offline_nbody(body);
152 if(body_array[off_index] == NULL || body_array[off_index]->s == NULL) {
153 LM_ERR("while constructing offline body\n");
157 LM_DBG("[user]=%.*s [domain]= %.*s\n", pres_user->len, pres_user->s,
158 pres_domain->len, pres_domain->s);
159 if(pxml_force_single_body == 0) {
160 n_body = agregate_xmls(pres_user, pres_domain, body_array, n);
162 n_body = agregate_xmls_priority(pres_user, pres_domain, body_array, n);
164 if(n_body == NULL && n != 0) {
165 LM_ERR("while aggregating body\n");
169 xmlFree(body_array[off_index]->s);
170 pkg_free(body_array[off_index]);
171 body_array[off_index] = body;
180 int pres_apply_auth(str *notify_body, subs_t *subs, str **final_nbody)
182 xmlDocPtr doc = NULL;
183 xmlNodePtr node = NULL;
187 if(pxml_force_active) {
191 if(subs->auth_rules_doc == NULL) {
192 LM_ERR("NULL rules doc\n");
195 doc = xmlParseMemory(subs->auth_rules_doc->s, subs->auth_rules_doc->len);
197 LM_ERR("parsing xml doc\n");
201 node = get_rule_node(subs, doc);
203 LM_DBG("The subscriber didn't match the conditions\n");
208 n_body = get_final_notify_body(subs, notify_body, node);
210 LM_ERR("in function get_final_notify_body\n");
219 *final_nbody = n_body;
223 str *get_final_notify_body(subs_t *subs, str *notify_body, xmlNodePtr rule_node)
225 xmlNodePtr transf_node = NULL, node = NULL, dont_provide = NULL;
226 xmlNodePtr doc_root = NULL, doc_node = NULL, provide_node = NULL;
227 xmlNodePtr all_node = NULL;
228 xmlDocPtr doc = NULL;
229 #define KSR_FNB_NAME_SIZE 24
230 char name[KSR_FNB_NAME_SIZE];
232 char service_uri_scheme[16];
233 int i = 0, found = 0;
234 str *new_body = NULL;
235 char *class_cont = NULL, *occurence_ID = NULL, *service_uri = NULL;
236 char *deviceID = NULL;
237 char *content = NULL;
238 char all_name[KSR_FNB_NAME_SIZE + 8];
240 doc = xmlParseMemory(notify_body->s, notify_body->len);
242 LM_ERR("while parsing the xml body message\n");
245 doc_root = xmlDocGetNodeByName(doc, "presence", NULL);
246 if(doc_root == NULL) {
247 LM_ERR("while extracting the presence node\n");
251 strcpy(all_name, "all-");
253 new_body = (str *)pkg_malloc(sizeof(str));
254 if(new_body == NULL) {
255 LM_ERR("while allocating memory\n");
258 memset(new_body, 0, sizeof(str));
260 transf_node = xmlNodeGetChildByName(rule_node, "transformations");
261 if(transf_node == NULL) {
262 LM_DBG("transformations node not found\n");
266 for(node = transf_node->children; node; node = node->next) {
267 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
270 /* handle 'provide-xyz' nodes */
271 name_len = strlen((char *)(node->name));
275 LM_DBG("transf_node->name:%s\n", node->name);
277 /* skip 'provide-' (e.g., provide-services) */
278 if(name_len - 8 > KSR_FNB_NAME_SIZE - 1) {
279 LM_INFO("unsupported handling of: %s\n", (char *)node->name);
282 strcpy((char *)name, (char *)(node->name + 8));
283 strcpy(all_name + 4, name);
285 if(xmlStrcasecmp((unsigned char *)name, (unsigned char *)"services")
287 strcpy(name, "tuple");
288 if(strncmp((char *)name, "person", 6) == 0)
291 doc_node = xmlNodeGetNodeByName(doc_root, name, NULL);
294 LM_DBG("searched doc_node->name:%s\n", name);
296 content = (char *)xmlNodeGetContent(node);
298 LM_DBG("content = %s\n", content);
300 if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"FALSE")
302 LM_DBG("found content false\n");
304 xmlUnlinkNode(doc_node);
305 xmlFreeNode(doc_node);
306 doc_node = xmlNodeGetChildByName(doc_root, name);
312 if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"TRUE")
314 LM_DBG("found content true\n");
322 if(xmlStrcasecmp(doc_node->name, (unsigned char *)"text") == 0) {
323 doc_node = doc_node->next;
327 if(xmlStrcasecmp(doc_node->name, (unsigned char *)name) != 0) {
330 all_node = xmlNodeGetChildByName(node, all_name);
333 LM_DBG("must provide all\n");
334 doc_node = doc_node->next;
339 class_cont = xmlNodeGetNodeContentByName(doc_node, "class", NULL);
340 if(class_cont == NULL)
341 LM_DBG("no class tag found\n");
343 LM_DBG("found class = %s\n", class_cont);
345 occurence_ID = xmlNodeGetAttrContentByName(doc_node, "id");
346 if(occurence_ID == NULL)
347 LM_DBG("no id found\n");
349 LM_DBG("found id = %s\n", occurence_ID);
352 deviceID = xmlNodeGetNodeContentByName(doc_node, "deviceID", NULL);
354 LM_DBG("no deviceID found\n");
356 LM_DBG("found deviceID = %s\n", deviceID);
360 xmlNodeGetNodeContentByName(doc_node, "contact", NULL);
361 if(service_uri == NULL)
362 LM_DBG("no service_uri found\n");
364 LM_DBG("found service_uri = %s\n", service_uri);
366 if(service_uri != NULL) {
367 while(service_uri[i] != ':') {
368 service_uri_scheme[i] = service_uri[i];
371 service_uri_scheme[i] = '\0';
372 LM_DBG("service_uri_scheme: %s\n", service_uri_scheme);
375 provide_node = node->children;
377 while(provide_node != NULL) {
378 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"text")
380 provide_node = provide_node->next;
384 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"class")
387 content = (char *)xmlNodeGetContent(provide_node);
390 && xmlStrcasecmp((unsigned char *)content,
391 (unsigned char *)class_cont)
394 LM_DBG("found class= %s", class_cont);
402 provide_node->name, (unsigned char *)"deviceID")
405 content = (char *)xmlNodeGetContent(provide_node);
408 && xmlStrcasecmp((unsigned char *)content,
409 (unsigned char *)deviceID)
412 LM_DBG("found deviceID= %s", deviceID);
420 provide_node->name, (unsigned char *)"occurence-id")
423 content = (char *)xmlNodeGetContent(provide_node);
425 && xmlStrcasecmp((unsigned char *)content,
426 (unsigned char *)occurence_ID)
429 LM_DBG("found occurenceID= %s\n", occurence_ID);
437 provide_node->name, (unsigned char *)"service-uri")
440 content = (char *)xmlNodeGetContent(provide_node);
442 && xmlStrcasecmp((unsigned char *)content,
443 (unsigned char *)service_uri)
446 LM_DBG("found service_uri= %s", service_uri);
454 if(xmlStrcasecmp(provide_node->name,
455 (unsigned char *)"service-uri-scheme")
458 content = (char *)xmlNodeGetContent(provide_node);
459 LM_DBG("service_uri_scheme=%s\n", content);
461 && xmlStrcasecmp((unsigned char *)content,
462 (unsigned char *)service_uri_scheme)
465 LM_DBG("found service_uri_scheme= %s",
474 provide_node = provide_node->next;
478 LM_DBG("delete node: %s\n", doc_node->name);
479 dont_provide = doc_node;
480 doc_node = doc_node->next;
481 xmlUnlinkNode(dont_provide);
482 xmlFreeNode(dont_provide);
484 doc_node = doc_node->next;
489 xmlDocDumpFormatMemory(
490 doc, (xmlChar **)(void *)&new_body->s, &new_body->len, 1);
491 LM_DBG("body = \n%.*s\n", new_body->len, new_body->s);
496 xmlFree(occurence_ID);
498 xmlFree(service_uri);
511 str *agregate_xmls(str *pres_user, str *pres_domain, str **body_array, int n)
513 int i, j = 0, append;
514 xmlNodePtr p_root = NULL, new_p_root = NULL;
515 xmlDocPtr *xml_array;
516 xmlNodePtr node = NULL;
517 xmlNodePtr add_node = NULL;
519 char *id = NULL, *tuple_id = NULL;
521 xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
522 if(xml_array == NULL) {
524 LM_ERR("while allocating memory");
527 memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
529 for(i = 0; i < n; i++) {
530 if(body_array[i] == NULL)
534 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
536 if(xml_array[j] == NULL) {
537 LM_ERR("while parsing xml body message\n");
543 if(j == 0) /* no body */
551 p_root = xmlDocGetNodeByName(xml_array[j], "presence", NULL);
553 LM_ERR("while getting the xml_tree root\n");
557 for(i = j - 1; i >= 0; i--) {
558 new_p_root = xmlDocGetNodeByName(xml_array[i], "presence", NULL);
559 if(new_p_root == NULL) {
560 LM_ERR("while getting the xml_tree root\n");
565 node = xmlNodeGetChildByName(new_p_root, "tuple");
567 tuple_id = xmlNodeGetAttrContentByName(node, "id");
568 if(tuple_id == NULL) {
569 LM_ERR("while extracting tuple id\n");
572 for(node = p_root->children; node != NULL; node = node->next) {
573 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
576 if(xmlStrcasecmp(node->name, (unsigned char *)"tuple") == 0) {
577 id = xmlNodeGetAttrContentByName(node, "id");
579 LM_ERR("while extracting tuple id\n");
584 (unsigned char *)tuple_id, (unsigned char *)id)
598 for(node = new_p_root->children; node; node = node->next) {
599 add_node = xmlCopyNode(node, 1);
600 if(add_node == NULL) {
601 LM_ERR("while copying node\n");
604 if(xmlAddChild(p_root, add_node) == NULL) {
605 LM_ERR("while adding child\n");
612 body = (str *)pkg_malloc(sizeof(str));
614 ERR_MEM(PKG_MEM_STR);
617 xmlDocDumpFormatMemory(
618 xml_array[j], (xmlChar **)(void *)&body->s, &body->len, 1);
620 for(i = 0; i <= j; i++) {
621 if(xml_array[i] != NULL)
622 xmlFreeDoc(xml_array[i]);
624 if(xml_array != NULL)
633 if(xml_array != NULL) {
634 for(i = 0; i <= j; i++) {
635 if(xml_array[i] != NULL)
636 xmlFreeDoc(xml_array[i]);
648 str *agregate_xmls_priority(str *pres_user, str *pres_domain, str **body_array, int n)
650 int i, j = 0, idx = 0;
651 xmlNodePtr p_root = NULL, new_p_root = NULL;
652 xmlDocPtr *xml_array;
654 char *cur = NULL, *cmp = NULL, *priority = NULL;
656 xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
657 if(xml_array == NULL) {
659 LM_ERR("while allocating memory");
662 memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
664 for(i = 0; i < n; i++) {
665 if(body_array[i] == NULL)
669 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
671 if(xml_array[j] == NULL) {
672 LM_ERR("while parsing xml body message\n");
678 if(j == 0) /* no body */
686 if(strlen(pxml_single_body_priorities.s) > 0
687 && strlen(pxml_single_body_lookup_element.s) > 0) {
688 p_root = xmlDocGetNodeByName(xml_array[j], "presence", NULL);
690 LM_ERR("while getting the xml_tree root\n");
693 cur = xmlNodeGetNodeContentByName(p_root, pxml_single_body_lookup_element.s, NULL);
695 priority = strstr(pxml_single_body_priorities.s, cur);
698 for(i = j - 1; i >= 0; i--) {
699 new_p_root = xmlDocGetNodeByName(xml_array[i], "presence", NULL);
700 if(new_p_root == NULL) {
701 LM_ERR("while getting the xml_tree root\n");
705 cmp = xmlNodeGetNodeContentByName(new_p_root, pxml_single_body_lookup_element.s, NULL);
706 if(cur != NULL && cmp != NULL && strcasecmp(cur,cmp)) {
707 char *x1 = strstr(pxml_single_body_priorities.s, cmp);
717 body = (str *)pkg_malloc(sizeof(str));
719 ERR_MEM(PKG_MEM_STR);
722 xmlDocDumpFormatMemory(
723 xml_array[idx], (xmlChar **)(void *)&body->s, &body->len, 1);
725 for(i = 0; i <= j; i++) {
726 if(xml_array[i] != NULL)
727 xmlFreeDoc(xml_array[i]);
729 if(xml_array != NULL)
738 if(xml_array != NULL) {
739 for(i = 0; i <= j; i++) {
740 if(xml_array[i] != NULL)
741 xmlFreeDoc(xml_array[i]);
751 str *offline_nbody(str *body)
753 xmlDocPtr doc = NULL;
754 xmlDocPtr new_doc = NULL;
755 xmlNodePtr node, tuple_node = NULL, status_node;
756 xmlNodePtr root_node, add_node, pres_node;
759 doc = xmlParseMemory(body->s, body->len);
761 LM_ERR("while parsing xml memory\n");
764 node = xmlDocGetNodeByName(doc, "basic", NULL);
766 LM_ERR("while extracting basic node\n");
769 xmlNodeSetContent(node, (const unsigned char *)"closed");
771 tuple_node = xmlDocGetNodeByName(doc, "tuple", NULL);
772 if(tuple_node == NULL) {
773 LM_ERR("while extracting tuple node\n");
776 status_node = xmlDocGetNodeByName(doc, "status", NULL);
777 if(status_node == NULL) {
778 LM_ERR("while extracting tuple node\n");
782 pres_node = xmlDocGetNodeByName(doc, "presence", NULL);
784 LM_ERR("while extracting presence node\n");
788 new_doc = xmlNewDoc(BAD_CAST "1.0");
791 root_node = xmlCopyNode(pres_node, 2);
792 if(root_node == NULL) {
793 LM_ERR("while copying node\n");
796 xmlDocSetRootElement(new_doc, root_node);
798 tuple_node = xmlCopyNode(tuple_node, 2);
799 if(tuple_node == NULL) {
800 LM_ERR("while copying node\n");
803 xmlAddChild(root_node, tuple_node);
805 add_node = xmlCopyNode(status_node, 1);
806 if(add_node == NULL) {
807 LM_ERR("while copying node\n");
810 xmlAddChild(tuple_node, add_node);
812 new_body = (str *)pkg_malloc(sizeof(str));
813 if(new_body == NULL) {
814 ERR_MEM(PKG_MEM_STR);
816 memset(new_body, 0, sizeof(str));
818 xmlDocDumpFormatMemory(
819 new_doc, (xmlChar **)(void *)&new_body->s, &new_body->len, 1);