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 force_dummy_presence;
42 extern int presence_force_single_body;
43 extern str presence_single_body_priorities;
44 extern str presence_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 && (!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(presence_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;
190 if(subs->auth_rules_doc == NULL) {
191 LM_ERR("NULL rules doc\n");
194 doc = xmlParseMemory(subs->auth_rules_doc->s, subs->auth_rules_doc->len);
196 LM_ERR("parsing xml doc\n");
200 node = get_rule_node(subs, doc);
202 LM_DBG("The subscriber didn't match the conditions\n");
207 n_body = get_final_notify_body(subs, notify_body, node);
209 LM_ERR("in function get_final_notify_body\n");
218 *final_nbody = n_body;
222 str *get_final_notify_body(subs_t *subs, str *notify_body, xmlNodePtr rule_node)
224 xmlNodePtr transf_node = NULL, node = NULL, dont_provide = NULL;
225 xmlNodePtr doc_root = NULL, doc_node = NULL, provide_node = NULL;
226 xmlNodePtr all_node = NULL;
227 xmlDocPtr doc = NULL;
228 #define KSR_FNB_NAME_SIZE 24
229 char name[KSR_FNB_NAME_SIZE];
231 char service_uri_scheme[16];
232 int i = 0, found = 0;
233 str *new_body = NULL;
234 char *class_cont = NULL, *occurence_ID = NULL, *service_uri = NULL;
235 char *deviceID = NULL;
236 char *content = NULL;
237 char all_name[KSR_FNB_NAME_SIZE + 8];
239 doc = xmlParseMemory(notify_body->s, notify_body->len);
241 LM_ERR("while parsing the xml body message\n");
244 doc_root = xmlDocGetNodeByName(doc, "presence", NULL);
245 if(doc_root == NULL) {
246 LM_ERR("while extracting the presence node\n");
250 strcpy(all_name, "all-");
252 new_body = (str *)pkg_malloc(sizeof(str));
253 if(new_body == NULL) {
254 LM_ERR("while allocating memory\n");
257 memset(new_body, 0, sizeof(str));
259 transf_node = xmlNodeGetChildByName(rule_node, "transformations");
260 if(transf_node == NULL) {
261 LM_DBG("transformations node not found\n");
265 for(node = transf_node->children; node; node = node->next) {
266 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
269 /* handle 'provide-xyz' nodes */
270 name_len = strlen((char *)(node->name));
274 LM_DBG("transf_node->name:%s\n", node->name);
276 /* skip 'provide-' (e.g., provide-services) */
277 if(name_len - 8 > KSR_FNB_NAME_SIZE - 1) {
278 LM_INFO("unsupported handling of: %s\n", (char *)node->name);
281 strcpy((char *)name, (char *)(node->name + 8));
282 strcpy(all_name + 4, name);
284 if(xmlStrcasecmp((unsigned char *)name, (unsigned char *)"services")
286 strcpy(name, "tuple");
287 if(strncmp((char *)name, "person", 6) == 0)
290 doc_node = xmlNodeGetNodeByName(doc_root, name, NULL);
293 LM_DBG("searched doc_node->name:%s\n", name);
295 content = (char *)xmlNodeGetContent(node);
297 LM_DBG("content = %s\n", content);
299 if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"FALSE")
301 LM_DBG("found content false\n");
303 xmlUnlinkNode(doc_node);
304 xmlFreeNode(doc_node);
305 doc_node = xmlNodeGetChildByName(doc_root, name);
311 if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"TRUE")
313 LM_DBG("found content true\n");
321 if(xmlStrcasecmp(doc_node->name, (unsigned char *)"text") == 0) {
322 doc_node = doc_node->next;
326 if(xmlStrcasecmp(doc_node->name, (unsigned char *)name) != 0) {
329 all_node = xmlNodeGetChildByName(node, all_name);
332 LM_DBG("must provide all\n");
333 doc_node = doc_node->next;
338 class_cont = xmlNodeGetNodeContentByName(doc_node, "class", NULL);
339 if(class_cont == NULL)
340 LM_DBG("no class tag found\n");
342 LM_DBG("found class = %s\n", class_cont);
344 occurence_ID = xmlNodeGetAttrContentByName(doc_node, "id");
345 if(occurence_ID == NULL)
346 LM_DBG("no id found\n");
348 LM_DBG("found id = %s\n", occurence_ID);
351 deviceID = xmlNodeGetNodeContentByName(doc_node, "deviceID", NULL);
353 LM_DBG("no deviceID found\n");
355 LM_DBG("found deviceID = %s\n", deviceID);
359 xmlNodeGetNodeContentByName(doc_node, "contact", NULL);
360 if(service_uri == NULL)
361 LM_DBG("no service_uri found\n");
363 LM_DBG("found service_uri = %s\n", service_uri);
365 if(service_uri != NULL) {
366 while(service_uri[i] != ':') {
367 service_uri_scheme[i] = service_uri[i];
370 service_uri_scheme[i] = '\0';
371 LM_DBG("service_uri_scheme: %s\n", service_uri_scheme);
374 provide_node = node->children;
376 while(provide_node != NULL) {
377 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"text")
379 provide_node = provide_node->next;
383 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"class")
386 content = (char *)xmlNodeGetContent(provide_node);
389 && xmlStrcasecmp((unsigned char *)content,
390 (unsigned char *)class_cont)
393 LM_DBG("found class= %s", class_cont);
401 provide_node->name, (unsigned char *)"deviceID")
404 content = (char *)xmlNodeGetContent(provide_node);
407 && xmlStrcasecmp((unsigned char *)content,
408 (unsigned char *)deviceID)
411 LM_DBG("found deviceID= %s", deviceID);
419 provide_node->name, (unsigned char *)"occurence-id")
422 content = (char *)xmlNodeGetContent(provide_node);
424 && xmlStrcasecmp((unsigned char *)content,
425 (unsigned char *)occurence_ID)
428 LM_DBG("found occurenceID= %s\n", occurence_ID);
436 provide_node->name, (unsigned char *)"service-uri")
439 content = (char *)xmlNodeGetContent(provide_node);
441 && xmlStrcasecmp((unsigned char *)content,
442 (unsigned char *)service_uri)
445 LM_DBG("found service_uri= %s", service_uri);
453 if(xmlStrcasecmp(provide_node->name,
454 (unsigned char *)"service-uri-scheme")
457 content = (char *)xmlNodeGetContent(provide_node);
458 LM_DBG("service_uri_scheme=%s\n", content);
460 && xmlStrcasecmp((unsigned char *)content,
461 (unsigned char *)service_uri_scheme)
464 LM_DBG("found service_uri_scheme= %s",
473 provide_node = provide_node->next;
477 LM_DBG("delete node: %s\n", doc_node->name);
478 dont_provide = doc_node;
479 doc_node = doc_node->next;
480 xmlUnlinkNode(dont_provide);
481 xmlFreeNode(dont_provide);
483 doc_node = doc_node->next;
488 xmlDocDumpFormatMemory(
489 doc, (xmlChar **)(void *)&new_body->s, &new_body->len, 1);
490 LM_DBG("body = \n%.*s\n", new_body->len, new_body->s);
495 xmlFree(occurence_ID);
497 xmlFree(service_uri);
510 str *agregate_xmls(str *pres_user, str *pres_domain, str **body_array, int n)
512 int i, j = 0, append;
513 xmlNodePtr p_root = NULL, new_p_root = NULL;
514 xmlDocPtr *xml_array;
515 xmlNodePtr node = NULL;
516 xmlNodePtr add_node = NULL;
518 char *id = NULL, *tuple_id = NULL;
520 xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
521 if(xml_array == NULL) {
523 LM_ERR("while allocating memory");
526 memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
528 for(i = 0; i < n; i++) {
529 if(body_array[i] == NULL)
533 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
535 if(xml_array[j] == NULL) {
536 LM_ERR("while parsing xml body message\n");
542 if(j == 0) /* no body */
550 p_root = xmlDocGetNodeByName(xml_array[j], "presence", NULL);
552 LM_ERR("while getting the xml_tree root\n");
556 for(i = j - 1; i >= 0; i--) {
557 new_p_root = xmlDocGetNodeByName(xml_array[i], "presence", NULL);
558 if(new_p_root == NULL) {
559 LM_ERR("while getting the xml_tree root\n");
564 node = xmlNodeGetChildByName(new_p_root, "tuple");
566 tuple_id = xmlNodeGetAttrContentByName(node, "id");
567 if(tuple_id == NULL) {
568 LM_ERR("while extracting tuple id\n");
571 for(node = p_root->children; node != NULL; node = node->next) {
572 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
575 if(xmlStrcasecmp(node->name, (unsigned char *)"tuple") == 0) {
576 id = xmlNodeGetAttrContentByName(node, "id");
578 LM_ERR("while extracting tuple id\n");
583 (unsigned char *)tuple_id, (unsigned char *)id)
597 for(node = new_p_root->children; node; node = node->next) {
598 add_node = xmlCopyNode(node, 1);
599 if(add_node == NULL) {
600 LM_ERR("while copying node\n");
603 if(xmlAddChild(p_root, add_node) == NULL) {
604 LM_ERR("while adding child\n");
611 body = (str *)pkg_malloc(sizeof(str));
613 ERR_MEM(PKG_MEM_STR);
616 xmlDocDumpFormatMemory(
617 xml_array[j], (xmlChar **)(void *)&body->s, &body->len, 1);
619 for(i = 0; i <= j; i++) {
620 if(xml_array[i] != NULL)
621 xmlFreeDoc(xml_array[i]);
623 if(xml_array != NULL)
632 if(xml_array != NULL) {
633 for(i = 0; i <= j; i++) {
634 if(xml_array[i] != NULL)
635 xmlFreeDoc(xml_array[i]);
647 str *agregate_xmls_priority(str *pres_user, str *pres_domain, str **body_array, int n)
649 int i, j = 0, idx = 0;
650 xmlNodePtr p_root = NULL, new_p_root = NULL;
651 xmlDocPtr *xml_array;
653 char *cur = NULL, *cmp = NULL, *priority = NULL;
655 xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
656 if(xml_array == NULL) {
658 LM_ERR("while allocating memory");
661 memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
663 for(i = 0; i < n; i++) {
664 if(body_array[i] == NULL)
668 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
670 if(xml_array[j] == NULL) {
671 LM_ERR("while parsing xml body message\n");
677 if(j == 0) /* no body */
685 if(strlen(presence_single_body_priorities.s) > 0 && strlen(presence_single_body_lookup_element.s) > 0) {
686 p_root = xmlDocGetNodeByName(xml_array[j], "presence", NULL);
688 LM_ERR("while getting the xml_tree root\n");
691 cur = xmlNodeGetNodeContentByName(p_root, presence_single_body_lookup_element.s, NULL);
693 priority = strstr(presence_single_body_priorities.s, cur);
696 for(i = j - 1; i >= 0; i--) {
697 new_p_root = xmlDocGetNodeByName(xml_array[i], "presence", NULL);
698 if(new_p_root == NULL) {
699 LM_ERR("while getting the xml_tree root\n");
703 cmp = xmlNodeGetNodeContentByName(new_p_root, presence_single_body_lookup_element.s, NULL);
704 if(cur != NULL && cmp != NULL && strcasecmp(cur,cmp)) {
705 char *x1 = strstr(presence_single_body_priorities.s, cmp);
715 body = (str *)pkg_malloc(sizeof(str));
717 ERR_MEM(PKG_MEM_STR);
720 xmlDocDumpFormatMemory(
721 xml_array[idx], (xmlChar **)(void *)&body->s, &body->len, 1);
723 for(i = 0; i <= j; i++) {
724 if(xml_array[i] != NULL)
725 xmlFreeDoc(xml_array[i]);
727 if(xml_array != NULL)
736 if(xml_array != NULL) {
737 for(i = 0; i <= j; i++) {
738 if(xml_array[i] != NULL)
739 xmlFreeDoc(xml_array[i]);
749 str *offline_nbody(str *body)
751 xmlDocPtr doc = NULL;
752 xmlDocPtr new_doc = NULL;
753 xmlNodePtr node, tuple_node = NULL, status_node;
754 xmlNodePtr root_node, add_node, pres_node;
757 doc = xmlParseMemory(body->s, body->len);
759 LM_ERR("while parsing xml memory\n");
762 node = xmlDocGetNodeByName(doc, "basic", NULL);
764 LM_ERR("while extracting basic node\n");
767 xmlNodeSetContent(node, (const unsigned char *)"closed");
769 tuple_node = xmlDocGetNodeByName(doc, "tuple", NULL);
770 if(tuple_node == NULL) {
771 LM_ERR("while extracting tuple node\n");
774 status_node = xmlDocGetNodeByName(doc, "status", NULL);
775 if(status_node == NULL) {
776 LM_ERR("while extracting tuple node\n");
780 pres_node = xmlDocGetNodeByName(doc, "presence", NULL);
782 LM_ERR("while extracting presence node\n");
786 new_doc = xmlNewDoc(BAD_CAST "1.0");
789 root_node = xmlCopyNode(pres_node, 2);
790 if(root_node == NULL) {
791 LM_ERR("while copying node\n");
794 xmlDocSetRootElement(new_doc, root_node);
796 tuple_node = xmlCopyNode(tuple_node, 2);
797 if(tuple_node == NULL) {
798 LM_ERR("while copying node\n");
801 xmlAddChild(root_node, tuple_node);
803 add_node = xmlCopyNode(status_node, 1);
804 if(add_node == NULL) {
805 LM_ERR("while copying node\n");
808 xmlAddChild(tuple_node, add_node);
810 new_body = (str *)pkg_malloc(sizeof(str));
811 if(new_body == NULL) {
812 ERR_MEM(PKG_MEM_STR);
814 memset(new_body, 0, sizeof(str));
816 xmlDocDumpFormatMemory(
817 new_doc, (xmlChar **)(void *)&new_body->s, &new_body->len, 1);