presence_xml: do not allocate memory before getting presence node
[sip-router] / src / modules / presence_xml / notify_body.c
1 /*
2  * $Id: notify_body.c 1337 2006-12-07 18:05:05Z bogdan_iancu $
3  *
4  * presence_xml module -  
5  *
6  * Copyright (C) 2006 Voice Sistem S.R.L.
7  *
8  * This file is part of Kamailio, a free SIP server.
9  *
10  * Kamailio is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * Kamailio is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License 
21  * along with this program; if not, write to the Free Software 
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  * History:
25  * --------
26  *  2007-04-11  initial version (anca)
27  */
28 /*! \file
29  * \brief Kamailio Presence_XML :: Notify BODY handling
30  * \ingroup presence_xml
31  */
32
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <libxml/parser.h>
37
38 #include "../../core/mem/mem.h"
39 #include "../presence/utils_func.h"
40 #include "../presence/hash.h"
41 #include "xcap_auth.h"
42 #include "pidf.h"
43 #include "notify_body.h"
44 #include "presence_xml.h"
45
46 extern int force_dummy_presence;
47
48 str* offline_nbody(str* body);
49 str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n);
50 str* get_final_notify_body( 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  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
64 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\" xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" xmlns:c=\"urn:ietf:params:xml:ns:pidf:cipid\" entity=\"%.*s\"> \
65 <tuple xmlns=\"urn:ietf:params:xml:ns:pidf\" id=\"615293b33c62dec073e05d9421e9f48b\">\
66 <status>\
67 <basic>open</basic>\
68 </status>\
69 </tuple>\
70 <note xmlns=\"urn:ietf:params:xml:ns:pidf\">Available</note>\
71 <dm:person xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" id=\"1\">\
72 <rpid:activities/>\
73 <dm:note>Available</dm:note>\
74 </dm:person>\
75 </presence>"
76
77 str* pres_agg_nbody_empty(str* pres_user, str* pres_domain)
78 {
79         str* n_body= NULL;
80
81         str* body_array;
82         char* body;
83
84         LM_DBG("creating empty presence for [pres_user]=%.*s [pres_domain]= %.*s\n",
85                         pres_user->len, pres_user->s, pres_domain->len, pres_domain->s);
86
87         if(pres_user->len+sizeof(PRESENCE_EMPTY_BODY)
88                         >= PRESENCE_EMPTY_BODY_SIZE - 1) {
89                 LM_ERR("insufficient buffer to add user (its len is: %d)\n",
90                                 pres_user->len);
91                 return NULL;
92         }
93         body_array = (str*)pkg_malloc(sizeof(str));
94         if(body_array==NULL) {
95                 LM_ERR("no more pkg\n");
96                 return NULL;
97         }
98
99         body = (char*)pkg_malloc(PRESENCE_EMPTY_BODY_SIZE);
100         if(body_array==NULL) {
101                 LM_ERR("no more pkg\n");
102                 pkg_free(body_array);
103                 return NULL;
104         }
105         snprintf(body, PRESENCE_EMPTY_BODY_SIZE, PRESENCE_EMPTY_BODY, pres_user->len, pres_user->s);
106         body_array->s = body;
107         body_array->len = strlen(body);
108
109
110         n_body= agregate_xmls(pres_user, pres_domain, &body_array, 1);
111         LM_DBG("[n_body]=%p\n", n_body);
112         if(n_body) {
113                 LM_DBG("[*n_body]=%.*s\n", n_body->len, n_body->s);
114         }
115         if(n_body== NULL) {
116                 LM_ERR("while aggregating body for: %.*s\n", pres_user->len, pres_user->s);
117         }
118
119         pkg_free(body);
120         pkg_free(body_array);
121
122
123         xmlCleanupParser();
124         xmlMemoryDump();
125
126         return n_body;
127 }
128
129 str* pres_agg_nbody(str* pres_user, str* pres_domain, str** body_array, int n, int off_index)
130 {
131         str* n_body= NULL;
132         str* body= NULL;
133
134         if(body_array== NULL && (!force_dummy_presence))
135                 return NULL;
136
137         if(body_array== NULL)
138                 return pres_agg_nbody_empty(pres_user, pres_domain);
139
140         if(off_index>= 0)
141         {
142                 body= body_array[off_index];
143                 body_array[off_index]= offline_nbody(body);
144
145                 if(body_array[off_index]== NULL || body_array[off_index]->s== NULL)
146                 {
147                         LM_ERR("while constructing offline body\n");
148                         return NULL;
149                 }
150         }
151         LM_DBG("[user]=%.*s  [domain]= %.*s\n",
152                         pres_user->len, pres_user->s, pres_domain->len, pres_domain->s);
153         n_body= agregate_xmls(pres_user, pres_domain, body_array, n);
154         if(n_body== NULL && n!= 0)
155         {
156                 LM_ERR("while aggregating body\n");
157         }
158
159         if(off_index>= 0)
160         {
161                 xmlFree(body_array[off_index]->s);
162                 pkg_free(body_array[off_index]);
163                 body_array[off_index]= body;
164         }
165
166         xmlCleanupParser();
167     xmlMemoryDump();
168
169         return n_body;
170 }       
171
172 int pres_apply_auth(str* notify_body, subs_t* subs, str** final_nbody)
173 {
174         xmlDocPtr doc= NULL;
175         xmlNodePtr node= NULL;
176         str* n_body= NULL;
177         
178         *final_nbody= NULL;
179         if(force_active)
180                 return 0;
181
182         if(subs->auth_rules_doc== NULL)
183         {
184                 LM_ERR("NULL rules doc\n");
185                 return -1;
186         }
187         doc= xmlParseMemory(subs->auth_rules_doc->s, subs->auth_rules_doc->len);
188         if(doc== NULL)
189         {
190                 LM_ERR("parsing xml doc\n");
191                 return -1;
192         }
193         
194         node= get_rule_node(subs, doc);
195         if(node== NULL)
196         {
197                 LM_DBG("The subscriber didn't match the conditions\n");
198                 xmlFreeDoc(doc);
199                 return 0;
200         }
201         
202         n_body= get_final_notify_body(subs, notify_body, node);
203         if(n_body== NULL)
204         {
205                 LM_ERR("in function get_final_notify_body\n");
206                 xmlFreeDoc(doc);
207                 return -1;
208         }
209
210         xmlFreeDoc(doc);
211         xmlCleanupParser();
212     xmlMemoryDump();
213
214         *final_nbody= n_body;
215         return 1;
216
217 }       
218
219 str* get_final_notify_body( subs_t *subs, str* notify_body, xmlNodePtr rule_node)
220 {
221         xmlNodePtr transf_node = NULL, node = NULL, dont_provide = NULL;
222         xmlNodePtr doc_root = NULL, doc_node = NULL, provide_node = NULL;
223         xmlNodePtr all_node = NULL;
224         xmlDocPtr doc= NULL;
225 #define KSR_FNB_NAME_SIZE       24
226         char name[KSR_FNB_NAME_SIZE];
227         int name_len;
228         char service_uri_scheme[16];
229         int i= 0, found = 0;
230         str* new_body = NULL;
231     char* class_cont = NULL, *occurence_ID= NULL, *service_uri= NULL;
232         char* deviceID = NULL;
233         char* content = NULL;
234         char all_name[KSR_FNB_NAME_SIZE+8];
235
236         doc = xmlParseMemory(notify_body->s, notify_body->len);
237         if(doc== NULL) 
238         {
239                 LM_ERR("while parsing the xml body message\n");
240                 goto error;
241         }
242         doc_root = xmlDocGetNodeByName(doc,"presence", NULL);
243         if(doc_root == NULL)
244         {
245                 LM_ERR("while extracting the presence node\n");
246                 goto error;
247         }
248
249         strcpy(all_name, "all-");
250
251         new_body = (str*)pkg_malloc(sizeof(str));
252         if(new_body == NULL)
253         {
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         {
262                 LM_DBG("transformations node not found\n");
263                 goto done;
264         }
265         
266         for(node = transf_node->children; node; node = node->next )
267         {
268                 if(xmlStrcasecmp(node->name, (unsigned char*)"text")== 0)
269                         continue;
270
271                 /* handle 'provide-xyz' nodes */
272                 name_len = strlen((char*)(node->name));
273                 if(name_len<9) {
274                         continue;
275                 }
276                 LM_DBG("transf_node->name:%s\n", node->name);
277
278                 /* skip 'provide-' (e.g., provide-services) */
279                 if(name_len-8>KSR_FNB_NAME_SIZE-1) {
280                         LM_INFO("unsupported handling of: %s\n", (char*)node->name);
281                         continue;
282                 }
283                 strcpy((char*)name, (char*)(node->name + 8));
284                 strcpy(all_name+4, name);
285                 
286                 if(xmlStrcasecmp((unsigned char*)name,(unsigned char*)"services") == 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                 {
299                         LM_DBG("content = %s\n", content);
300                 
301                         if(xmlStrcasecmp((unsigned char*)content,
302                                         (unsigned char*) "FALSE") == 0)
303                         {
304                                 LM_DBG("found content false\n");
305                                 while( doc_node )
306                                 {
307                                         xmlUnlinkNode(doc_node);        
308                                         xmlFreeNode(doc_node);
309                                         doc_node = xmlNodeGetChildByName(doc_root, name);
310                                 }
311                                 xmlFree(content);
312                                 continue;
313                         }
314                 
315                         if(xmlStrcasecmp((unsigned char*)content,
316                                         (unsigned char*) "TRUE") == 0)
317                         {
318                                 LM_DBG("found content true\n");
319                                 xmlFree(content);
320                                 continue;
321                         }
322                         xmlFree(content);
323                 }
324
325                 while (doc_node )
326                 {
327                         if (xmlStrcasecmp(doc_node->name,(unsigned char*)"text")==0)
328                         {
329                                 doc_node = doc_node->next;
330                                 continue;
331                         }
332
333                         if (xmlStrcasecmp(doc_node->name,(unsigned char*)name)!=0)
334                         {
335                                 break;
336                         }
337                         all_node = xmlNodeGetChildByName(node, all_name) ;
338                 
339                         if( all_node )
340                         {
341                                 LM_DBG("must provide all\n");
342                                 doc_node = doc_node->next;
343                                 continue;
344                         }
345
346                         found = 0;
347                         class_cont = xmlNodeGetNodeContentByName(doc_node, "class", 
348                                         NULL);
349                         if(class_cont == NULL)
350                                 LM_DBG("no class tag found\n");
351                         else
352                                 LM_DBG("found class = %s\n", class_cont);
353
354                         occurence_ID = xmlNodeGetAttrContentByName(doc_node, "id");
355                         if(occurence_ID == NULL)
356                                 LM_DBG("no id found\n");
357                         else
358                                 LM_DBG("found id = %s\n", occurence_ID);
359
360
361                         deviceID = xmlNodeGetNodeContentByName(doc_node, "deviceID",
362                                         NULL);  
363                         if(deviceID== NULL)
364                                 LM_DBG("no deviceID found\n");
365                         else
366                                 LM_DBG("found deviceID = %s\n", deviceID);
367
368
369                         service_uri = xmlNodeGetNodeContentByName(doc_node, "contact",
370                                         NULL);  
371                         if(service_uri == NULL)
372                                 LM_DBG("no service_uri found\n");
373                         else
374                                 LM_DBG("found service_uri = %s\n", service_uri);
375                         i = 0;
376                         if(service_uri!= NULL)
377                         {
378                                 while(service_uri[i]!= ':')
379                                 {
380                                         service_uri_scheme[i] = service_uri[i];
381                                         i++;
382                                 }
383                                 service_uri_scheme[i] = '\0';
384                                 LM_DBG("service_uri_scheme: %s\n", service_uri_scheme);
385                         }
386
387                         provide_node = node->children;
388                                 
389                         while ( provide_node!= NULL )
390                         {
391                                 if(xmlStrcasecmp(provide_node->name,(unsigned char*) "text")==0)
392                                 {
393                                         provide_node =  provide_node->next;
394                                         continue;
395                                 }
396
397                                 if(xmlStrcasecmp(provide_node->name,(unsigned char*)"class")== 0
398                                                 && class_cont )
399                                 {
400                                         content = (char*)xmlNodeGetContent(provide_node);
401
402                                         if(content&& xmlStrcasecmp((unsigned char*)content,
403                                                                 (unsigned char*)class_cont) == 0)
404                                         {
405                                                 found = 1;
406                                                 LM_DBG("found class= %s", class_cont);
407                                                 xmlFree(content);
408                                                 break;
409                                         }
410                                         if(content)
411                                                 xmlFree(content);
412                                 }
413                                 if(xmlStrcasecmp(provide_node->name,
414                                                         (unsigned char*) "deviceID")==0&&deviceID )
415                                 {
416                                         content = (char*)xmlNodeGetContent(provide_node);
417
418                                         if(content && xmlStrcasecmp ((unsigned char*)content,
419                                                                 (unsigned char*)deviceID) == 0)
420                                         {
421                                                 found = 1;
422                                                 LM_DBG("found deviceID= %s", deviceID);
423                                                 xmlFree(content);
424                                                 break;
425                                         }
426                                         if(content)
427                                                 xmlFree(content);
428
429                                 }
430                                 if(xmlStrcasecmp(provide_node->name,
431                                                         (unsigned char*)"occurence-id")== 0&& occurence_ID)
432                                 {
433                                         content = (char*)xmlNodeGetContent(provide_node);
434                                         if(content && xmlStrcasecmp ((unsigned char*)content,
435                                                                 (unsigned char*)occurence_ID) == 0)
436                                         {
437                                                 found = 1;
438                                                 LM_DBG("found occurenceID= %s\n", occurence_ID);
439                                                 xmlFree(content);
440                                                 break;
441                                         }
442                                         if(content)
443                                                 xmlFree(content);
444
445                                 }
446                                 if(xmlStrcasecmp(provide_node->name,
447                                                         (unsigned char*)"service-uri")== 0 && service_uri)
448                                 {
449                                         content = (char*)xmlNodeGetContent(provide_node);
450                                         if(content&& xmlStrcasecmp ((unsigned char*)content,
451                                                                 (unsigned char*)service_uri) == 0)
452                                         {
453                                                 found = 1;
454                                                 LM_DBG("found service_uri= %s", service_uri);
455                                                 xmlFree(content);
456                                                 break;
457                                         }
458                                         if(content)
459                                                 xmlFree(content);
460
461                                 }
462                         
463                                 if(xmlStrcasecmp(provide_node->name,
464                                                 (unsigned char*)"service-uri-scheme")==0&& i)
465                                 {
466                                         content = (char*)xmlNodeGetContent(provide_node);
467                                         LM_DBG("service_uri_scheme=%s\n",content);
468                                         if(content && xmlStrcasecmp((unsigned char*)content,
469                                                                 (unsigned char*)service_uri_scheme) == 0)
470                                         {
471                                                 found = 1;
472                                                 LM_DBG("found service_uri_scheme= %s", service_uri_scheme);
473                                                 xmlFree(content);
474                                                 break;
475                                         }       
476                                         if(content)
477                                                 xmlFree(content);
478
479                                 }
480
481                                 provide_node = provide_node->next;
482                         }
483                         
484                         if(found == 0)
485                         {
486                                 LM_DBG("delete node: %s\n", doc_node->name);
487                                 dont_provide = doc_node;
488                                 doc_node = doc_node->next;
489                                 xmlUnlinkNode(dont_provide);    
490                                 xmlFreeNode(dont_provide);
491                         }       
492                         else
493                                 doc_node = doc_node->next;
494         
495                 }
496         }
497
498 done:
499         xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&new_body->s,
500                         &new_body->len, 1);
501         LM_DBG("body = \n%.*s\n", new_body->len,
502                         new_body->s);
503
504         xmlFreeDoc(doc);
505
506         xmlFree(class_cont);
507         xmlFree(occurence_ID);
508         xmlFree(deviceID);
509         xmlFree(service_uri);
510         xmlCleanupParser();
511         xmlMemoryDump();
512
513         return new_body;
514
515 error:
516     if(doc) {
517                 xmlFreeDoc(doc);
518         }
519         return NULL;
520 }       
521
522 str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n)
523 {
524         int i, j= 0, append ;
525         xmlNodePtr p_root= NULL, new_p_root= NULL ;
526         xmlDocPtr* xml_array ;
527         xmlNodePtr node = NULL;
528         xmlNodePtr add_node = NULL ;
529         str *body= NULL;
530         char* id= NULL, *tuple_id = NULL;
531
532         xml_array = (xmlDocPtr*)pkg_malloc( (n+2)*sizeof(xmlDocPtr));
533         if(xml_array== NULL)
534         {
535         
536                 LM_ERR("while allocating memory");
537                 return NULL;
538         }
539         memset(xml_array, 0, (n+2)*sizeof(xmlDocPtr)) ;
540
541         for(i=0; i<n; i++)
542         {
543                 if(body_array[i] == NULL )
544                         continue;
545
546                 xml_array[j] = NULL;
547                 xml_array[j] = xmlParseMemory( body_array[i]->s, body_array[i]->len );
548                 
549                 if( xml_array[j]== NULL)
550                 {
551                         LM_ERR("while parsing xml body message\n");
552                         goto error;
553                 }
554                 j++;
555
556         } 
557
558         if(j== 0)  /* no body */
559         {
560                 if(xml_array)
561                         pkg_free(xml_array);
562                 return NULL;
563         }
564
565         j--;
566         p_root = xmlDocGetNodeByName( xml_array[j], "presence", NULL);
567         if(p_root ==NULL)
568         {
569                 LM_ERR("while getting the xml_tree root\n");
570                 goto error;
571         }
572
573         for(i= j-1; i>=0; i--)
574         {
575                 new_p_root= xmlDocGetNodeByName( xml_array[i], "presence", NULL);
576                 if(new_p_root ==NULL)
577                 {
578                         LM_ERR("while getting the xml_tree root\n");
579                         goto error;
580                 }
581
582                 append= 1;
583                 node= xmlNodeGetChildByName(new_p_root, "tuple");
584                 if(node != NULL)
585                 {
586                         tuple_id= xmlNodeGetAttrContentByName(node, "id");
587                         if(tuple_id== NULL)
588                         {
589                                 LM_ERR("while extracting tuple id\n");
590                                 goto error;
591                         }
592                         for (node = p_root->children; node!=NULL; node = node->next)
593                         {               
594                                 if( xmlStrcasecmp(node->name,(unsigned char*)"text")==0)
595                                         continue;
596                         
597                                 if( xmlStrcasecmp(node->name,(unsigned char*)"tuple")==0)
598                                 {
599                                         id = xmlNodeGetAttrContentByName(node, "id");
600                                         if(id== NULL)
601                                         {
602                                                 LM_ERR("while extracting tuple id\n");
603                                                 goto error;
604                                         }
605                                 
606                                         if(xmlStrcasecmp((unsigned char*)tuple_id,
607                                                                 (unsigned char*)id )== 0)
608                                         {
609                                                 append = 0;
610                                                 xmlFree(id);
611                                                 break;
612                                         }
613                                         xmlFree(id);
614                                 }
615                         }
616                         xmlFree(tuple_id);
617                         tuple_id= NULL;
618                 }
619
620                 if(append) 
621                 {       
622                         for(node= new_p_root->children; node; node= node->next)
623                         {       
624                                 add_node= xmlCopyNode(node, 1);
625                                 if(add_node== NULL)
626                                 {
627                                         LM_ERR("while copying node\n");
628                                         goto error;
629                                 }
630                                 if(xmlAddChild(p_root, add_node)== NULL)
631                                 {
632                                         LM_ERR("while adding child\n");
633                                         goto error;
634                                 }
635                                                                 
636                         }
637                 }
638         }
639
640         body = (str*)pkg_malloc(sizeof(str));
641         if(body == NULL)
642         {
643                 ERR_MEM(PKG_MEM_STR);
644         }
645
646         xmlDocDumpFormatMemory(xml_array[j],(xmlChar**)(void*)&body->s, 
647                         &body->len, 1); 
648
649         for(i=0; i<=j; i++)
650         {
651                 if(xml_array[i]!=NULL)
652                         xmlFreeDoc( xml_array[i]);
653         }
654         if(xml_array!=NULL)
655                 pkg_free(xml_array);
656     
657         xmlCleanupParser();
658     xmlMemoryDump();
659
660         return body;
661
662 error:
663         if(xml_array!=NULL)
664         {
665                 for(i=0; i<=j; i++)
666                 {
667                         if(xml_array[i]!=NULL)
668                                 xmlFreeDoc( xml_array[i]);
669                 }
670                 pkg_free(xml_array);
671         }
672         if(tuple_id)
673                 xmlFree(tuple_id);
674         if(body)
675                 pkg_free(body);
676
677         return NULL;
678 }
679
680 str* offline_nbody(str* body)
681 {
682         xmlDocPtr doc= NULL;
683         xmlDocPtr new_doc= NULL;
684         xmlNodePtr node, tuple_node= NULL, status_node;
685         xmlNodePtr root_node, add_node, pres_node;
686         str* new_body;
687
688         doc= xmlParseMemory(body->s, body->len);
689         if(doc==  NULL)
690         {
691                 LM_ERR("while parsing xml memory\n");
692                 return NULL;
693         }
694         node= xmlDocGetNodeByName(doc, "basic", NULL);
695         if(node== NULL)
696         {
697                 LM_ERR("while extracting basic node\n");
698                 goto error;
699         }
700         xmlNodeSetContent(node, (const unsigned char*)"closed");
701
702         tuple_node= xmlDocGetNodeByName(doc, "tuple", NULL);
703         if(tuple_node== NULL)
704         {
705                 LM_ERR("while extracting tuple node\n");
706                 goto error;
707         }
708         status_node= xmlDocGetNodeByName(doc, "status", NULL);
709         if(status_node== NULL)
710         {
711                 LM_ERR("while extracting tuple node\n");
712                 goto error;
713         }
714
715         pres_node= xmlDocGetNodeByName(doc, "presence", NULL);
716         if(node== NULL)
717         {
718                 LM_ERR("while extracting presence node\n");
719                 goto error;
720         }
721
722     new_doc = xmlNewDoc(BAD_CAST "1.0");
723     if(new_doc==0)
724                 goto error;
725         root_node= xmlCopyNode(pres_node, 2);
726         if(root_node== NULL)
727         {
728                 LM_ERR("while copying node\n");
729                 goto error;
730         }
731     xmlDocSetRootElement(new_doc, root_node);
732
733         tuple_node= xmlCopyNode(tuple_node, 2);
734         if(tuple_node== NULL)
735         {
736                 LM_ERR("while copying node\n");
737                 goto error;
738         }
739         xmlAddChild(root_node, tuple_node);
740
741         add_node= xmlCopyNode(status_node, 1);
742         if(add_node== NULL)
743         {
744                 LM_ERR("while copying node\n");
745                 goto error;
746         }
747         xmlAddChild(tuple_node, add_node);
748
749         new_body = (str*)pkg_malloc(sizeof(str));
750         if(new_body == NULL)
751         {
752                 ERR_MEM(PKG_MEM_STR);
753         }
754         memset(new_body, 0, sizeof(str));
755
756         xmlDocDumpFormatMemory(new_doc,(xmlChar**)(void*)&new_body->s,
757                 &new_body->len, 1);
758
759         xmlFreeDoc(doc);
760         xmlFreeDoc(new_doc);
761         xmlCleanupParser();
762         xmlMemoryDump();
763
764         return new_body;
765
766 error:
767         if(doc)
768                 xmlFreeDoc(doc);
769         if(new_doc)
770                 xmlFreeDoc(new_doc);
771         return NULL;
772
773 }               
774