4f5492f06891572aa1506cfc393aec34fa8ac223
[sip-router] / src / modules / presence_xml / notify_body.c
1 /*
2  * presence_xml module
3  *
4  * Copyright (C) 2006 Voice Sistem S.R.L.
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
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
12  *
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.
17  *
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
21  *
22  */
23 /*! \file
24  * \brief Kamailio Presence_XML :: Notify BODY handling
25  * \ingroup presence_xml
26  */
27
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <libxml/parser.h>
32
33 #include "../../core/mem/mem.h"
34 #include "../presence/utils_func.h"
35 #include "../presence/hash.h"
36 #include "xcap_auth.h"
37 #include "pidf.h"
38 #include "notify_body.h"
39 #include "presence_xml.h"
40
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;
45
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);
51
52 void free_xml_body(char *body)
53 {
54         if(body == NULL)
55                 return;
56
57         xmlFree(body);
58         body = NULL;
59 }
60
61 #define PRESENCE_EMPTY_BODY_SIZE 1024
62
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\">\
70 <status>\
71 <basic>open</basic>\
72 </status>\
73 </tuple>\
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\">\
77 <rpid:activities/>\
78 <dm:note>Available</dm:note>\
79 </dm:person>\
80 </presence>"
81
82 str *pres_agg_nbody_empty(str *pres_user, str *pres_domain)
83 {
84         str *n_body = NULL;
85
86         str *body_array;
87         char *body;
88
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);
91
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",
95                                 pres_user->len);
96                 return NULL;
97         }
98         body_array = (str *)pkg_malloc(sizeof(str));
99         if(body_array == NULL) {
100                 LM_ERR("no more pkg\n");
101                 return NULL;
102         }
103
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);
108                 return NULL;
109         }
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);
114
115
116         n_body = agregate_xmls(pres_user, pres_domain, &body_array, 1);
117         LM_DBG("[n_body]=%p\n", n_body);
118         if(n_body) {
119                 LM_DBG("[*n_body]=%.*s\n", n_body->len, n_body->s);
120         }
121         if(n_body == NULL) {
122                 LM_ERR("while aggregating body for: %.*s\n", pres_user->len,
123                                 pres_user->s);
124         }
125
126         pkg_free(body);
127         pkg_free(body_array);
128
129
130         xmlCleanupParser();
131         xmlMemoryDump();
132
133         return n_body;
134 }
135
136 str *pres_agg_nbody(str *pres_user, str *pres_domain, str **body_array, int n,
137                 int off_index)
138 {
139         str *n_body = NULL;
140         str *body = NULL;
141
142         if(body_array == NULL && (!force_dummy_presence))
143                 return NULL;
144
145         if(body_array == NULL)
146                 return pres_agg_nbody_empty(pres_user, pres_domain);
147
148         if(off_index >= 0) {
149                 body = body_array[off_index];
150                 body_array[off_index] = offline_nbody(body);
151
152                 if(body_array[off_index] == NULL || body_array[off_index]->s == NULL) {
153                         LM_ERR("while constructing offline body\n");
154                         return NULL;
155                 }
156         }
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);
161         } else {
162                 n_body = agregate_xmls_priority(pres_user, pres_domain, body_array, n);
163         }
164         if(n_body == NULL && n != 0) {
165                 LM_ERR("while aggregating body\n");
166         }
167
168         if(off_index >= 0) {
169                 xmlFree(body_array[off_index]->s);
170                 pkg_free(body_array[off_index]);
171                 body_array[off_index] = body;
172         }
173
174         xmlCleanupParser();
175         xmlMemoryDump();
176
177         return n_body;
178 }
179
180 int pres_apply_auth(str *notify_body, subs_t *subs, str **final_nbody)
181 {
182         xmlDocPtr doc = NULL;
183         xmlNodePtr node = NULL;
184         str *n_body = NULL;
185
186         *final_nbody = NULL;
187         if(force_active)
188                 return 0;
189
190         if(subs->auth_rules_doc == NULL) {
191                 LM_ERR("NULL rules doc\n");
192                 return -1;
193         }
194         doc = xmlParseMemory(subs->auth_rules_doc->s, subs->auth_rules_doc->len);
195         if(doc == NULL) {
196                 LM_ERR("parsing xml doc\n");
197                 return -1;
198         }
199
200         node = get_rule_node(subs, doc);
201         if(node == NULL) {
202                 LM_DBG("The subscriber didn't match the conditions\n");
203                 xmlFreeDoc(doc);
204                 return 0;
205         }
206
207         n_body = get_final_notify_body(subs, notify_body, node);
208         if(n_body == NULL) {
209                 LM_ERR("in function get_final_notify_body\n");
210                 xmlFreeDoc(doc);
211                 return -1;
212         }
213
214         xmlFreeDoc(doc);
215         xmlCleanupParser();
216         xmlMemoryDump();
217
218         *final_nbody = n_body;
219         return 1;
220 }
221
222 str *get_final_notify_body(subs_t *subs, str *notify_body, xmlNodePtr rule_node)
223 {
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];
230         int name_len;
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];
238
239         doc = xmlParseMemory(notify_body->s, notify_body->len);
240         if(doc == NULL) {
241                 LM_ERR("while parsing the xml body message\n");
242                 goto error;
243         }
244         doc_root = xmlDocGetNodeByName(doc, "presence", NULL);
245         if(doc_root == NULL) {
246                 LM_ERR("while extracting the presence node\n");
247                 goto error;
248         }
249
250         strcpy(all_name, "all-");
251
252         new_body = (str *)pkg_malloc(sizeof(str));
253         if(new_body == NULL) {
254                 LM_ERR("while allocating memory\n");
255                 return NULL;
256         }
257         memset(new_body, 0, sizeof(str));
258
259         transf_node = xmlNodeGetChildByName(rule_node, "transformations");
260         if(transf_node == NULL) {
261                 LM_DBG("transformations node not found\n");
262                 goto done;
263         }
264
265         for(node = transf_node->children; node; node = node->next) {
266                 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
267                         continue;
268
269                 /* handle 'provide-xyz' nodes */
270                 name_len = strlen((char *)(node->name));
271                 if(name_len < 9) {
272                         continue;
273                 }
274                 LM_DBG("transf_node->name:%s\n", node->name);
275
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);
279                         continue;
280                 }
281                 strcpy((char *)name, (char *)(node->name + 8));
282                 strcpy(all_name + 4, name);
283
284                 if(xmlStrcasecmp((unsigned char *)name, (unsigned char *)"services")
285                                 == 0)
286                         strcpy(name, "tuple");
287                 if(strncmp((char *)name, "person", 6) == 0)
288                         name[6] = '\0';
289
290                 doc_node = xmlNodeGetNodeByName(doc_root, name, NULL);
291                 if(doc_node == NULL)
292                         continue;
293                 LM_DBG("searched doc_node->name:%s\n", name);
294
295                 content = (char *)xmlNodeGetContent(node);
296                 if(content) {
297                         LM_DBG("content = %s\n", content);
298
299                         if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"FALSE")
300                                         == 0) {
301                                 LM_DBG("found content false\n");
302                                 while(doc_node) {
303                                         xmlUnlinkNode(doc_node);
304                                         xmlFreeNode(doc_node);
305                                         doc_node = xmlNodeGetChildByName(doc_root, name);
306                                 }
307                                 xmlFree(content);
308                                 continue;
309                         }
310
311                         if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"TRUE")
312                                         == 0) {
313                                 LM_DBG("found content true\n");
314                                 xmlFree(content);
315                                 continue;
316                         }
317                         xmlFree(content);
318                 }
319
320                 while(doc_node) {
321                         if(xmlStrcasecmp(doc_node->name, (unsigned char *)"text") == 0) {
322                                 doc_node = doc_node->next;
323                                 continue;
324                         }
325
326                         if(xmlStrcasecmp(doc_node->name, (unsigned char *)name) != 0) {
327                                 break;
328                         }
329                         all_node = xmlNodeGetChildByName(node, all_name);
330
331                         if(all_node) {
332                                 LM_DBG("must provide all\n");
333                                 doc_node = doc_node->next;
334                                 continue;
335                         }
336
337                         found = 0;
338                         class_cont = xmlNodeGetNodeContentByName(doc_node, "class", NULL);
339                         if(class_cont == NULL)
340                                 LM_DBG("no class tag found\n");
341                         else
342                                 LM_DBG("found class = %s\n", class_cont);
343
344                         occurence_ID = xmlNodeGetAttrContentByName(doc_node, "id");
345                         if(occurence_ID == NULL)
346                                 LM_DBG("no id found\n");
347                         else
348                                 LM_DBG("found id = %s\n", occurence_ID);
349
350
351                         deviceID = xmlNodeGetNodeContentByName(doc_node, "deviceID", NULL);
352                         if(deviceID == NULL)
353                                 LM_DBG("no deviceID found\n");
354                         else
355                                 LM_DBG("found deviceID = %s\n", deviceID);
356
357
358                         service_uri =
359                                         xmlNodeGetNodeContentByName(doc_node, "contact", NULL);
360                         if(service_uri == NULL)
361                                 LM_DBG("no service_uri found\n");
362                         else
363                                 LM_DBG("found service_uri = %s\n", service_uri);
364                         i = 0;
365                         if(service_uri != NULL) {
366                                 while(service_uri[i] != ':') {
367                                         service_uri_scheme[i] = service_uri[i];
368                                         i++;
369                                 }
370                                 service_uri_scheme[i] = '\0';
371                                 LM_DBG("service_uri_scheme: %s\n", service_uri_scheme);
372                         }
373
374                         provide_node = node->children;
375
376                         while(provide_node != NULL) {
377                                 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"text")
378                                                 == 0) {
379                                         provide_node = provide_node->next;
380                                         continue;
381                                 }
382
383                                 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"class")
384                                                                 == 0
385                                                 && class_cont) {
386                                         content = (char *)xmlNodeGetContent(provide_node);
387
388                                         if(content
389                                                         && xmlStrcasecmp((unsigned char *)content,
390                                                                            (unsigned char *)class_cont)
391                                                                            == 0) {
392                                                 found = 1;
393                                                 LM_DBG("found class= %s", class_cont);
394                                                 xmlFree(content);
395                                                 break;
396                                         }
397                                         if(content)
398                                                 xmlFree(content);
399                                 }
400                                 if(xmlStrcasecmp(
401                                                    provide_node->name, (unsigned char *)"deviceID")
402                                                                 == 0
403                                                 && deviceID) {
404                                         content = (char *)xmlNodeGetContent(provide_node);
405
406                                         if(content
407                                                         && xmlStrcasecmp((unsigned char *)content,
408                                                                            (unsigned char *)deviceID)
409                                                                            == 0) {
410                                                 found = 1;
411                                                 LM_DBG("found deviceID= %s", deviceID);
412                                                 xmlFree(content);
413                                                 break;
414                                         }
415                                         if(content)
416                                                 xmlFree(content);
417                                 }
418                                 if(xmlStrcasecmp(
419                                                    provide_node->name, (unsigned char *)"occurence-id")
420                                                                 == 0
421                                                 && occurence_ID) {
422                                         content = (char *)xmlNodeGetContent(provide_node);
423                                         if(content
424                                                         && xmlStrcasecmp((unsigned char *)content,
425                                                                            (unsigned char *)occurence_ID)
426                                                                            == 0) {
427                                                 found = 1;
428                                                 LM_DBG("found occurenceID= %s\n", occurence_ID);
429                                                 xmlFree(content);
430                                                 break;
431                                         }
432                                         if(content)
433                                                 xmlFree(content);
434                                 }
435                                 if(xmlStrcasecmp(
436                                                    provide_node->name, (unsigned char *)"service-uri")
437                                                                 == 0
438                                                 && service_uri) {
439                                         content = (char *)xmlNodeGetContent(provide_node);
440                                         if(content
441                                                         && xmlStrcasecmp((unsigned char *)content,
442                                                                            (unsigned char *)service_uri)
443                                                                            == 0) {
444                                                 found = 1;
445                                                 LM_DBG("found service_uri= %s", service_uri);
446                                                 xmlFree(content);
447                                                 break;
448                                         }
449                                         if(content)
450                                                 xmlFree(content);
451                                 }
452
453                                 if(xmlStrcasecmp(provide_node->name,
454                                                    (unsigned char *)"service-uri-scheme")
455                                                                 == 0
456                                                 && i) {
457                                         content = (char *)xmlNodeGetContent(provide_node);
458                                         LM_DBG("service_uri_scheme=%s\n", content);
459                                         if(content
460                                                         && xmlStrcasecmp((unsigned char *)content,
461                                                                            (unsigned char *)service_uri_scheme)
462                                                                            == 0) {
463                                                 found = 1;
464                                                 LM_DBG("found service_uri_scheme= %s",
465                                                                 service_uri_scheme);
466                                                 xmlFree(content);
467                                                 break;
468                                         }
469                                         if(content)
470                                                 xmlFree(content);
471                                 }
472
473                                 provide_node = provide_node->next;
474                         }
475
476                         if(found == 0) {
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);
482                         } else
483                                 doc_node = doc_node->next;
484                 }
485         }
486
487 done:
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);
491
492         xmlFreeDoc(doc);
493
494         xmlFree(class_cont);
495         xmlFree(occurence_ID);
496         xmlFree(deviceID);
497         xmlFree(service_uri);
498         xmlCleanupParser();
499         xmlMemoryDump();
500
501         return new_body;
502
503 error:
504         if(doc) {
505                 xmlFreeDoc(doc);
506         }
507         return NULL;
508 }
509
510 str *agregate_xmls(str *pres_user, str *pres_domain, str **body_array, int n)
511 {
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;
517         str *body = NULL;
518         char *id = NULL, *tuple_id = NULL;
519
520         xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
521         if(xml_array == NULL) {
522
523                 LM_ERR("while allocating memory");
524                 return NULL;
525         }
526         memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
527
528         for(i = 0; i < n; i++) {
529                 if(body_array[i] == NULL)
530                         continue;
531
532                 xml_array[j] = NULL;
533                 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
534
535                 if(xml_array[j] == NULL) {
536                         LM_ERR("while parsing xml body message\n");
537                         goto error;
538                 }
539                 j++;
540         }
541
542         if(j == 0) /* no body */
543         {
544                 if(xml_array)
545                         pkg_free(xml_array);
546                 return NULL;
547         }
548
549         j--;
550         p_root = xmlDocGetNodeByName(xml_array[j], "presence", NULL);
551         if(p_root == NULL) {
552                 LM_ERR("while getting the xml_tree root\n");
553                 goto error;
554         }
555
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");
560                         goto error;
561                 }
562
563                 append = 1;
564                 node = xmlNodeGetChildByName(new_p_root, "tuple");
565                 if(node != NULL) {
566                         tuple_id = xmlNodeGetAttrContentByName(node, "id");
567                         if(tuple_id == NULL) {
568                                 LM_ERR("while extracting tuple id\n");
569                                 goto error;
570                         }
571                         for(node = p_root->children; node != NULL; node = node->next) {
572                                 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
573                                         continue;
574
575                                 if(xmlStrcasecmp(node->name, (unsigned char *)"tuple") == 0) {
576                                         id = xmlNodeGetAttrContentByName(node, "id");
577                                         if(id == NULL) {
578                                                 LM_ERR("while extracting tuple id\n");
579                                                 goto error;
580                                         }
581
582                                         if(xmlStrcasecmp(
583                                                            (unsigned char *)tuple_id, (unsigned char *)id)
584                                                         == 0) {
585                                                 append = 0;
586                                                 xmlFree(id);
587                                                 break;
588                                         }
589                                         xmlFree(id);
590                                 }
591                         }
592                         xmlFree(tuple_id);
593                         tuple_id = NULL;
594                 }
595
596                 if(append) {
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");
601                                         goto error;
602                                 }
603                                 if(xmlAddChild(p_root, add_node) == NULL) {
604                                         LM_ERR("while adding child\n");
605                                         goto error;
606                                 }
607                         }
608                 }
609         }
610
611         body = (str *)pkg_malloc(sizeof(str));
612         if(body == NULL) {
613                 ERR_MEM(PKG_MEM_STR);
614         }
615
616         xmlDocDumpFormatMemory(
617                         xml_array[j], (xmlChar **)(void *)&body->s, &body->len, 1);
618
619         for(i = 0; i <= j; i++) {
620                 if(xml_array[i] != NULL)
621                         xmlFreeDoc(xml_array[i]);
622         }
623         if(xml_array != NULL)
624                 pkg_free(xml_array);
625
626         xmlCleanupParser();
627         xmlMemoryDump();
628
629         return body;
630
631 error:
632         if(xml_array != NULL) {
633                 for(i = 0; i <= j; i++) {
634                         if(xml_array[i] != NULL)
635                                 xmlFreeDoc(xml_array[i]);
636                 }
637                 pkg_free(xml_array);
638         }
639         if(tuple_id)
640                 xmlFree(tuple_id);
641         if(body)
642                 pkg_free(body);
643
644         return NULL;
645 }
646
647 str *agregate_xmls_priority(str *pres_user, str *pres_domain, str **body_array, int n)
648 {
649         int i, j = 0, idx = 0;
650         xmlNodePtr p_root = NULL, new_p_root = NULL;
651         xmlDocPtr *xml_array;
652         str *body = NULL;
653         char *cur = NULL, *cmp = NULL, *priority = NULL;
654
655         xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
656         if(xml_array == NULL) {
657
658                 LM_ERR("while allocating memory");
659                 return NULL;
660         }
661         memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
662
663         for(i = 0; i < n; i++) {
664                 if(body_array[i] == NULL)
665                         continue;
666
667                 xml_array[j] = NULL;
668                 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
669
670                 if(xml_array[j] == NULL) {
671                         LM_ERR("while parsing xml body message\n");
672                         goto error;
673                 }
674                 j++;
675         }
676
677         if(j == 0) /* no body */
678         {
679                 if(xml_array)
680                         pkg_free(xml_array);
681                 return NULL;
682         }
683
684         idx = --j;
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);
687                 if(p_root == NULL) {
688                         LM_ERR("while getting the xml_tree root\n");
689                         goto error;
690                 }
691                 cur = xmlNodeGetNodeContentByName(p_root, presence_single_body_lookup_element.s, NULL);
692                 if(cur) {
693                         priority = strstr(presence_single_body_priorities.s, cur);
694                 }
695
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");
700                                 goto error;
701                         }
702
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);
706                                 if(x1 > priority) {
707                                         idx = i;
708                                         cur = cmp;
709                                         priority = x1;
710                                 }
711                         }
712                 }
713         }
714
715         body = (str *)pkg_malloc(sizeof(str));
716         if(body == NULL) {
717                 ERR_MEM(PKG_MEM_STR);
718         }
719
720         xmlDocDumpFormatMemory(
721                         xml_array[idx], (xmlChar **)(void *)&body->s, &body->len, 1);
722
723         for(i = 0; i <= j; i++) {
724                 if(xml_array[i] != NULL)
725                         xmlFreeDoc(xml_array[i]);
726         }
727         if(xml_array != NULL)
728                 pkg_free(xml_array);
729
730         xmlCleanupParser();
731         xmlMemoryDump();
732
733         return body;
734
735 error:
736         if(xml_array != NULL) {
737                 for(i = 0; i <= j; i++) {
738                         if(xml_array[i] != NULL)
739                                 xmlFreeDoc(xml_array[i]);
740                 }
741                 pkg_free(xml_array);
742         }
743         if(body)
744                 pkg_free(body);
745
746         return NULL;
747 }
748
749 str *offline_nbody(str *body)
750 {
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;
755         str *new_body;
756
757         doc = xmlParseMemory(body->s, body->len);
758         if(doc == NULL) {
759                 LM_ERR("while parsing xml memory\n");
760                 return NULL;
761         }
762         node = xmlDocGetNodeByName(doc, "basic", NULL);
763         if(node == NULL) {
764                 LM_ERR("while extracting basic node\n");
765                 goto error;
766         }
767         xmlNodeSetContent(node, (const unsigned char *)"closed");
768
769         tuple_node = xmlDocGetNodeByName(doc, "tuple", NULL);
770         if(tuple_node == NULL) {
771                 LM_ERR("while extracting tuple node\n");
772                 goto error;
773         }
774         status_node = xmlDocGetNodeByName(doc, "status", NULL);
775         if(status_node == NULL) {
776                 LM_ERR("while extracting tuple node\n");
777                 goto error;
778         }
779
780         pres_node = xmlDocGetNodeByName(doc, "presence", NULL);
781         if(node == NULL) {
782                 LM_ERR("while extracting presence node\n");
783                 goto error;
784         }
785
786         new_doc = xmlNewDoc(BAD_CAST "1.0");
787         if(new_doc == 0)
788                 goto error;
789         root_node = xmlCopyNode(pres_node, 2);
790         if(root_node == NULL) {
791                 LM_ERR("while copying node\n");
792                 goto error;
793         }
794         xmlDocSetRootElement(new_doc, root_node);
795
796         tuple_node = xmlCopyNode(tuple_node, 2);
797         if(tuple_node == NULL) {
798                 LM_ERR("while copying node\n");
799                 goto error;
800         }
801         xmlAddChild(root_node, tuple_node);
802
803         add_node = xmlCopyNode(status_node, 1);
804         if(add_node == NULL) {
805                 LM_ERR("while copying node\n");
806                 goto error;
807         }
808         xmlAddChild(tuple_node, add_node);
809
810         new_body = (str *)pkg_malloc(sizeof(str));
811         if(new_body == NULL) {
812                 ERR_MEM(PKG_MEM_STR);
813         }
814         memset(new_body, 0, sizeof(str));
815
816         xmlDocDumpFormatMemory(
817                         new_doc, (xmlChar **)(void *)&new_body->s, &new_body->len, 1);
818
819         xmlFreeDoc(doc);
820         xmlFreeDoc(new_doc);
821         xmlCleanupParser();
822         xmlMemoryDump();
823
824         return new_body;
825
826 error:
827         if(doc)
828                 xmlFreeDoc(doc);
829         if(new_doc)
830                 xmlFreeDoc(new_doc);
831         return NULL;
832 }