presence_xml: use common prefix for global variables
[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 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;
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 && (!pxml_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(pxml_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(pxml_force_active) {
188                 return 0;
189         }
190
191         if(subs->auth_rules_doc == NULL) {
192                 LM_ERR("NULL rules doc\n");
193                 return -1;
194         }
195         doc = xmlParseMemory(subs->auth_rules_doc->s, subs->auth_rules_doc->len);
196         if(doc == NULL) {
197                 LM_ERR("parsing xml doc\n");
198                 return -1;
199         }
200
201         node = get_rule_node(subs, doc);
202         if(node == NULL) {
203                 LM_DBG("The subscriber didn't match the conditions\n");
204                 xmlFreeDoc(doc);
205                 return 0;
206         }
207
208         n_body = get_final_notify_body(subs, notify_body, node);
209         if(n_body == NULL) {
210                 LM_ERR("in function get_final_notify_body\n");
211                 xmlFreeDoc(doc);
212                 return -1;
213         }
214
215         xmlFreeDoc(doc);
216         xmlCleanupParser();
217         xmlMemoryDump();
218
219         *final_nbody = n_body;
220         return 1;
221 }
222
223 str *get_final_notify_body(subs_t *subs, str *notify_body, xmlNodePtr rule_node)
224 {
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];
231         int name_len;
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];
239
240         doc = xmlParseMemory(notify_body->s, notify_body->len);
241         if(doc == NULL) {
242                 LM_ERR("while parsing the xml body message\n");
243                 goto error;
244         }
245         doc_root = xmlDocGetNodeByName(doc, "presence", NULL);
246         if(doc_root == NULL) {
247                 LM_ERR("while extracting the presence node\n");
248                 goto error;
249         }
250
251         strcpy(all_name, "all-");
252
253         new_body = (str *)pkg_malloc(sizeof(str));
254         if(new_body == NULL) {
255                 LM_ERR("while allocating memory\n");
256                 return NULL;
257         }
258         memset(new_body, 0, sizeof(str));
259
260         transf_node = xmlNodeGetChildByName(rule_node, "transformations");
261         if(transf_node == NULL) {
262                 LM_DBG("transformations node not found\n");
263                 goto done;
264         }
265
266         for(node = transf_node->children; node; node = node->next) {
267                 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
268                         continue;
269
270                 /* handle 'provide-xyz' nodes */
271                 name_len = strlen((char *)(node->name));
272                 if(name_len < 9) {
273                         continue;
274                 }
275                 LM_DBG("transf_node->name:%s\n", node->name);
276
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);
280                         continue;
281                 }
282                 strcpy((char *)name, (char *)(node->name + 8));
283                 strcpy(all_name + 4, name);
284
285                 if(xmlStrcasecmp((unsigned char *)name, (unsigned char *)"services")
286                                 == 0)
287                         strcpy(name, "tuple");
288                 if(strncmp((char *)name, "person", 6) == 0)
289                         name[6] = '\0';
290
291                 doc_node = xmlNodeGetNodeByName(doc_root, name, NULL);
292                 if(doc_node == NULL)
293                         continue;
294                 LM_DBG("searched doc_node->name:%s\n", name);
295
296                 content = (char *)xmlNodeGetContent(node);
297                 if(content) {
298                         LM_DBG("content = %s\n", content);
299
300                         if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"FALSE")
301                                         == 0) {
302                                 LM_DBG("found content false\n");
303                                 while(doc_node) {
304                                         xmlUnlinkNode(doc_node);
305                                         xmlFreeNode(doc_node);
306                                         doc_node = xmlNodeGetChildByName(doc_root, name);
307                                 }
308                                 xmlFree(content);
309                                 continue;
310                         }
311
312                         if(xmlStrcasecmp((unsigned char *)content, (unsigned char *)"TRUE")
313                                         == 0) {
314                                 LM_DBG("found content true\n");
315                                 xmlFree(content);
316                                 continue;
317                         }
318                         xmlFree(content);
319                 }
320
321                 while(doc_node) {
322                         if(xmlStrcasecmp(doc_node->name, (unsigned char *)"text") == 0) {
323                                 doc_node = doc_node->next;
324                                 continue;
325                         }
326
327                         if(xmlStrcasecmp(doc_node->name, (unsigned char *)name) != 0) {
328                                 break;
329                         }
330                         all_node = xmlNodeGetChildByName(node, all_name);
331
332                         if(all_node) {
333                                 LM_DBG("must provide all\n");
334                                 doc_node = doc_node->next;
335                                 continue;
336                         }
337
338                         found = 0;
339                         class_cont = xmlNodeGetNodeContentByName(doc_node, "class", NULL);
340                         if(class_cont == NULL)
341                                 LM_DBG("no class tag found\n");
342                         else
343                                 LM_DBG("found class = %s\n", class_cont);
344
345                         occurence_ID = xmlNodeGetAttrContentByName(doc_node, "id");
346                         if(occurence_ID == NULL)
347                                 LM_DBG("no id found\n");
348                         else
349                                 LM_DBG("found id = %s\n", occurence_ID);
350
351
352                         deviceID = xmlNodeGetNodeContentByName(doc_node, "deviceID", NULL);
353                         if(deviceID == NULL)
354                                 LM_DBG("no deviceID found\n");
355                         else
356                                 LM_DBG("found deviceID = %s\n", deviceID);
357
358
359                         service_uri =
360                                         xmlNodeGetNodeContentByName(doc_node, "contact", NULL);
361                         if(service_uri == NULL)
362                                 LM_DBG("no service_uri found\n");
363                         else
364                                 LM_DBG("found service_uri = %s\n", service_uri);
365                         i = 0;
366                         if(service_uri != NULL) {
367                                 while(service_uri[i] != ':') {
368                                         service_uri_scheme[i] = service_uri[i];
369                                         i++;
370                                 }
371                                 service_uri_scheme[i] = '\0';
372                                 LM_DBG("service_uri_scheme: %s\n", service_uri_scheme);
373                         }
374
375                         provide_node = node->children;
376
377                         while(provide_node != NULL) {
378                                 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"text")
379                                                 == 0) {
380                                         provide_node = provide_node->next;
381                                         continue;
382                                 }
383
384                                 if(xmlStrcasecmp(provide_node->name, (unsigned char *)"class")
385                                                                 == 0
386                                                 && class_cont) {
387                                         content = (char *)xmlNodeGetContent(provide_node);
388
389                                         if(content
390                                                         && xmlStrcasecmp((unsigned char *)content,
391                                                                            (unsigned char *)class_cont)
392                                                                            == 0) {
393                                                 found = 1;
394                                                 LM_DBG("found class= %s", class_cont);
395                                                 xmlFree(content);
396                                                 break;
397                                         }
398                                         if(content)
399                                                 xmlFree(content);
400                                 }
401                                 if(xmlStrcasecmp(
402                                                    provide_node->name, (unsigned char *)"deviceID")
403                                                                 == 0
404                                                 && deviceID) {
405                                         content = (char *)xmlNodeGetContent(provide_node);
406
407                                         if(content
408                                                         && xmlStrcasecmp((unsigned char *)content,
409                                                                            (unsigned char *)deviceID)
410                                                                            == 0) {
411                                                 found = 1;
412                                                 LM_DBG("found deviceID= %s", deviceID);
413                                                 xmlFree(content);
414                                                 break;
415                                         }
416                                         if(content)
417                                                 xmlFree(content);
418                                 }
419                                 if(xmlStrcasecmp(
420                                                    provide_node->name, (unsigned char *)"occurence-id")
421                                                                 == 0
422                                                 && occurence_ID) {
423                                         content = (char *)xmlNodeGetContent(provide_node);
424                                         if(content
425                                                         && xmlStrcasecmp((unsigned char *)content,
426                                                                            (unsigned char *)occurence_ID)
427                                                                            == 0) {
428                                                 found = 1;
429                                                 LM_DBG("found occurenceID= %s\n", occurence_ID);
430                                                 xmlFree(content);
431                                                 break;
432                                         }
433                                         if(content)
434                                                 xmlFree(content);
435                                 }
436                                 if(xmlStrcasecmp(
437                                                    provide_node->name, (unsigned char *)"service-uri")
438                                                                 == 0
439                                                 && service_uri) {
440                                         content = (char *)xmlNodeGetContent(provide_node);
441                                         if(content
442                                                         && xmlStrcasecmp((unsigned char *)content,
443                                                                            (unsigned char *)service_uri)
444                                                                            == 0) {
445                                                 found = 1;
446                                                 LM_DBG("found service_uri= %s", service_uri);
447                                                 xmlFree(content);
448                                                 break;
449                                         }
450                                         if(content)
451                                                 xmlFree(content);
452                                 }
453
454                                 if(xmlStrcasecmp(provide_node->name,
455                                                    (unsigned char *)"service-uri-scheme")
456                                                                 == 0
457                                                 && i) {
458                                         content = (char *)xmlNodeGetContent(provide_node);
459                                         LM_DBG("service_uri_scheme=%s\n", content);
460                                         if(content
461                                                         && xmlStrcasecmp((unsigned char *)content,
462                                                                            (unsigned char *)service_uri_scheme)
463                                                                            == 0) {
464                                                 found = 1;
465                                                 LM_DBG("found service_uri_scheme= %s",
466                                                                 service_uri_scheme);
467                                                 xmlFree(content);
468                                                 break;
469                                         }
470                                         if(content)
471                                                 xmlFree(content);
472                                 }
473
474                                 provide_node = provide_node->next;
475                         }
476
477                         if(found == 0) {
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);
483                         } else
484                                 doc_node = doc_node->next;
485                 }
486         }
487
488 done:
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);
492
493         xmlFreeDoc(doc);
494
495         xmlFree(class_cont);
496         xmlFree(occurence_ID);
497         xmlFree(deviceID);
498         xmlFree(service_uri);
499         xmlCleanupParser();
500         xmlMemoryDump();
501
502         return new_body;
503
504 error:
505         if(doc) {
506                 xmlFreeDoc(doc);
507         }
508         return NULL;
509 }
510
511 str *agregate_xmls(str *pres_user, str *pres_domain, str **body_array, int n)
512 {
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;
518         str *body = NULL;
519         char *id = NULL, *tuple_id = NULL;
520
521         xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
522         if(xml_array == NULL) {
523
524                 LM_ERR("while allocating memory");
525                 return NULL;
526         }
527         memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
528
529         for(i = 0; i < n; i++) {
530                 if(body_array[i] == NULL)
531                         continue;
532
533                 xml_array[j] = NULL;
534                 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
535
536                 if(xml_array[j] == NULL) {
537                         LM_ERR("while parsing xml body message\n");
538                         goto error;
539                 }
540                 j++;
541         }
542
543         if(j == 0) /* no body */
544         {
545                 if(xml_array)
546                         pkg_free(xml_array);
547                 return NULL;
548         }
549
550         j--;
551         p_root = xmlDocGetNodeByName(xml_array[j], "presence", NULL);
552         if(p_root == NULL) {
553                 LM_ERR("while getting the xml_tree root\n");
554                 goto error;
555         }
556
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");
561                         goto error;
562                 }
563
564                 append = 1;
565                 node = xmlNodeGetChildByName(new_p_root, "tuple");
566                 if(node != NULL) {
567                         tuple_id = xmlNodeGetAttrContentByName(node, "id");
568                         if(tuple_id == NULL) {
569                                 LM_ERR("while extracting tuple id\n");
570                                 goto error;
571                         }
572                         for(node = p_root->children; node != NULL; node = node->next) {
573                                 if(xmlStrcasecmp(node->name, (unsigned char *)"text") == 0)
574                                         continue;
575
576                                 if(xmlStrcasecmp(node->name, (unsigned char *)"tuple") == 0) {
577                                         id = xmlNodeGetAttrContentByName(node, "id");
578                                         if(id == NULL) {
579                                                 LM_ERR("while extracting tuple id\n");
580                                                 goto error;
581                                         }
582
583                                         if(xmlStrcasecmp(
584                                                            (unsigned char *)tuple_id, (unsigned char *)id)
585                                                         == 0) {
586                                                 append = 0;
587                                                 xmlFree(id);
588                                                 break;
589                                         }
590                                         xmlFree(id);
591                                 }
592                         }
593                         xmlFree(tuple_id);
594                         tuple_id = NULL;
595                 }
596
597                 if(append) {
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");
602                                         goto error;
603                                 }
604                                 if(xmlAddChild(p_root, add_node) == NULL) {
605                                         LM_ERR("while adding child\n");
606                                         goto error;
607                                 }
608                         }
609                 }
610         }
611
612         body = (str *)pkg_malloc(sizeof(str));
613         if(body == NULL) {
614                 ERR_MEM(PKG_MEM_STR);
615         }
616
617         xmlDocDumpFormatMemory(
618                         xml_array[j], (xmlChar **)(void *)&body->s, &body->len, 1);
619
620         for(i = 0; i <= j; i++) {
621                 if(xml_array[i] != NULL)
622                         xmlFreeDoc(xml_array[i]);
623         }
624         if(xml_array != NULL)
625                 pkg_free(xml_array);
626
627         xmlCleanupParser();
628         xmlMemoryDump();
629
630         return body;
631
632 error:
633         if(xml_array != NULL) {
634                 for(i = 0; i <= j; i++) {
635                         if(xml_array[i] != NULL)
636                                 xmlFreeDoc(xml_array[i]);
637                 }
638                 pkg_free(xml_array);
639         }
640         if(tuple_id)
641                 xmlFree(tuple_id);
642         if(body)
643                 pkg_free(body);
644
645         return NULL;
646 }
647
648 str *agregate_xmls_priority(str *pres_user, str *pres_domain, str **body_array, int n)
649 {
650         int i, j = 0, idx = 0;
651         xmlNodePtr p_root = NULL, new_p_root = NULL;
652         xmlDocPtr *xml_array;
653         str *body = NULL;
654         char *cur = NULL, *cmp = NULL, *priority = NULL;
655
656         xml_array = (xmlDocPtr *)pkg_malloc((n + 2) * sizeof(xmlDocPtr));
657         if(xml_array == NULL) {
658
659                 LM_ERR("while allocating memory");
660                 return NULL;
661         }
662         memset(xml_array, 0, (n + 2) * sizeof(xmlDocPtr));
663
664         for(i = 0; i < n; i++) {
665                 if(body_array[i] == NULL)
666                         continue;
667
668                 xml_array[j] = NULL;
669                 xml_array[j] = xmlParseMemory(body_array[i]->s, body_array[i]->len);
670
671                 if(xml_array[j] == NULL) {
672                         LM_ERR("while parsing xml body message\n");
673                         goto error;
674                 }
675                 j++;
676         }
677
678         if(j == 0) /* no body */
679         {
680                 if(xml_array)
681                         pkg_free(xml_array);
682                 return NULL;
683         }
684
685         idx = --j;
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);
689                 if(p_root == NULL) {
690                         LM_ERR("while getting the xml_tree root\n");
691                         goto error;
692                 }
693                 cur = xmlNodeGetNodeContentByName(p_root, pxml_single_body_lookup_element.s, NULL);
694                 if(cur) {
695                         priority = strstr(pxml_single_body_priorities.s, cur);
696                 }
697
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");
702                                 goto error;
703                         }
704
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);
708                                 if(x1 > priority) {
709                                         idx = i;
710                                         cur = cmp;
711                                         priority = x1;
712                                 }
713                         }
714                 }
715         }
716
717         body = (str *)pkg_malloc(sizeof(str));
718         if(body == NULL) {
719                 ERR_MEM(PKG_MEM_STR);
720         }
721
722         xmlDocDumpFormatMemory(
723                         xml_array[idx], (xmlChar **)(void *)&body->s, &body->len, 1);
724
725         for(i = 0; i <= j; i++) {
726                 if(xml_array[i] != NULL)
727                         xmlFreeDoc(xml_array[i]);
728         }
729         if(xml_array != NULL)
730                 pkg_free(xml_array);
731
732         xmlCleanupParser();
733         xmlMemoryDump();
734
735         return body;
736
737 error:
738         if(xml_array != NULL) {
739                 for(i = 0; i <= j; i++) {
740                         if(xml_array[i] != NULL)
741                                 xmlFreeDoc(xml_array[i]);
742                 }
743                 pkg_free(xml_array);
744         }
745         if(body)
746                 pkg_free(body);
747
748         return NULL;
749 }
750
751 str *offline_nbody(str *body)
752 {
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;
757         str *new_body;
758
759         doc = xmlParseMemory(body->s, body->len);
760         if(doc == NULL) {
761                 LM_ERR("while parsing xml memory\n");
762                 return NULL;
763         }
764         node = xmlDocGetNodeByName(doc, "basic", NULL);
765         if(node == NULL) {
766                 LM_ERR("while extracting basic node\n");
767                 goto error;
768         }
769         xmlNodeSetContent(node, (const unsigned char *)"closed");
770
771         tuple_node = xmlDocGetNodeByName(doc, "tuple", NULL);
772         if(tuple_node == NULL) {
773                 LM_ERR("while extracting tuple node\n");
774                 goto error;
775         }
776         status_node = xmlDocGetNodeByName(doc, "status", NULL);
777         if(status_node == NULL) {
778                 LM_ERR("while extracting tuple node\n");
779                 goto error;
780         }
781
782         pres_node = xmlDocGetNodeByName(doc, "presence", NULL);
783         if(node == NULL) {
784                 LM_ERR("while extracting presence node\n");
785                 goto error;
786         }
787
788         new_doc = xmlNewDoc(BAD_CAST "1.0");
789         if(new_doc == 0)
790                 goto error;
791         root_node = xmlCopyNode(pres_node, 2);
792         if(root_node == NULL) {
793                 LM_ERR("while copying node\n");
794                 goto error;
795         }
796         xmlDocSetRootElement(new_doc, root_node);
797
798         tuple_node = xmlCopyNode(tuple_node, 2);
799         if(tuple_node == NULL) {
800                 LM_ERR("while copying node\n");
801                 goto error;
802         }
803         xmlAddChild(root_node, tuple_node);
804
805         add_node = xmlCopyNode(status_node, 1);
806         if(add_node == NULL) {
807                 LM_ERR("while copying node\n");
808                 goto error;
809         }
810         xmlAddChild(tuple_node, add_node);
811
812         new_body = (str *)pkg_malloc(sizeof(str));
813         if(new_body == NULL) {
814                 ERR_MEM(PKG_MEM_STR);
815         }
816         memset(new_body, 0, sizeof(str));
817
818         xmlDocDumpFormatMemory(
819                         new_doc, (xmlChar **)(void *)&new_body->s, &new_body->len, 1);
820
821         xmlFreeDoc(doc);
822         xmlFreeDoc(new_doc);
823         xmlCleanupParser();
824         xmlMemoryDump();
825
826         return new_body;
827
828 error:
829         if(doc)
830                 xmlFreeDoc(doc);
831         if(new_doc)
832                 xmlFreeDoc(new_doc);
833         return NULL;
834 }