1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2014 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  *    if any, must include the following acknowledgment:
22  *       "This product includes software developed by the
23  *        Kannel Group (http://www.kannel.org/)."
24  *    Alternately, this acknowledgment may appear in the software itself,
25  *    if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  *    endorse or promote products derived from this software without
29  *    prior written permission. For written permission, please
30  *    contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  *    nor may "Kannel" appear in their name, without prior written
34  *    permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group.  For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * gwlib/xmlrpc.c: functions to handle XML-RPC structure - building and parsing
59  *
60  * XML-RPC is HTTP-based XML defination to handle remote procedure calls,
61  * and is defined at http://www.xml-rpc.org
62  *
63  * Kalle Marjola 2001 for project Kannel
64  * Stipe Tolj <stolj@wapme.de>
65  * Robert Gaach <robert.galach@my.tenbit.pl>
66  */
67 
68 #include <libxml/xmlmemory.h>
69 #include <libxml/tree.h>
70 #include <libxml/debugXML.h>
71 #include <libxml/encoding.h>
72 
73 #include "gwlib/gwlib.h"
74 #include "gwlib/xmlrpc.h"
75 
76 #define XR_ENABLE_EMPTY_STRING_VALUES
77 
78 #define OPTIMAL_STRUCT_SIZE 7
79 
80 typedef struct xmlrpc_methodresponse XMLRPCMethodResponse;
81 typedef struct xmlrpc_member XMLRPCMember;
82 typedef struct xmlrpc_methodcall XMLRPCMethodCall;
83 typedef struct xmlrpc_fault XMLRPCFault;
84 
85 typedef struct xmlrpc_table_t xmlrpc_table_t;
86 typedef struct xmlrpc_2table_t xmlrpc_2table_t;
87 
88 
89 struct xmlrpc_methodcall {
90     Octstr *method_name;
91     List *params;         /* List of XMLRPCValues */
92 };
93 
94 struct xmlrpc_methodresponse {
95     XMLRPCValue *param;         /* Param value */
96     XMLRPCFault *fault;         /* ..or this */
97 };
98 
99 struct xmlrpc_fault {
100     long f_code;                /* Fault code */
101     Octstr *f_string;           /* and description */
102 };
103 
104 struct xmlrpc_document {
105     int d_type;           /* enum here */
106     int parse_status;     /* enum here */
107     Octstr *parse_error;  /* error string in case of parsing error */
108     XMLRPCMethodCall *methodcall;
109     XMLRPCMethodResponse *methodresponse;
110 };
111 
112 struct xmlrpc_value {
113     int v_type;         /* enum here */
114     XMLRPCScalar *v_scalar;
115     List *v_array;     /* List of XMLRPCValues */
116     Dict *v_struct;    /* Dict of XMLRPCValues */
117 };
118 
119 struct xmlrpc_member {  /* member of struct */
120     Octstr *name;
121     XMLRPCValue *value;
122 };
123 
124 struct xmlrpc_scalar {
125     int s_type;         /* enum here */
126     Octstr *s_str;
127     long s_int;
128     int s_bool;
129     double s_double;
130     Octstr *s_date;
131     Octstr *s_base64;
132 };
133 
134 struct xmlrpc_table_t {
135     char *name;
136 };
137 
138 struct xmlrpc_2table_t {
139     char *name;
140     int s_type; /* enum here */
141 };
142 
143 static xmlrpc_table_t methodcall_elements[] = {
144     { "METHODNAME" },
145     { "PARAMS" }
146 };
147 
148 static xmlrpc_table_t methodresponse_elements[] = {
149     { "FAULT" },
150     { "PARAMS" }
151 };
152 
153 static xmlrpc_table_t params_elements[] = {
154     { "PARAM" }
155 };
156 
157 static xmlrpc_table_t param_elements[] = {
158     { "VALUE" }
159 };
160 
161 static xmlrpc_2table_t value_elements[] = {
162     { "I4", xr_int },
163     { "INT", xr_int },
164     { "BOOLEAN", xr_bool },
165     { "STRING", xr_string },
166     { "DOUBLE", xr_double },
167     { "DATETIME.ISO8601", xr_date },
168     { "BASE64", xr_base64 },
169     { "STRUCT", xr_struct },
170     { "ARRAY", xr_array }
171 };
172 
173 static xmlrpc_table_t struct_elements[] = {
174     { "MEMBER" }
175 };
176 
177 static xmlrpc_table_t member_elements[] = {
178     { "NAME" },
179     { "VALUE" }
180 };
181 
182 static xmlrpc_table_t array_elements[] = {
183     { "DATA" }
184 };
185 
186 static xmlrpc_table_t data_elements[] = {
187     { "VALUE" }
188 };
189 
190 static xmlrpc_table_t fault_elements[] = {
191     { "VALUE" }
192 };
193 
194 #define NUMBER_OF_METHODCALL_ELEMENTS \
195     sizeof(methodcall_elements)/sizeof(methodcall_elements[0])
196 #define NUMBER_OF_METHODRESPONSE_ELEMENTS \
197     sizeof(methodresponse_elements)/sizeof(methodresponse_elements[0])
198 #define NUMBER_OF_PARAMS_ELEMENTS \
199     sizeof(params_elements)/sizeof(params_elements[0])
200 #define NUMBER_OF_PARAM_ELEMENTS \
201     sizeof(param_elements)/sizeof(param_elements[0])
202 #define NUMBER_OF_VALUE_ELEMENTS \
203     sizeof(value_elements)/sizeof(value_elements[0])
204 #define NUMBER_OF_STRUCT_ELEMENTS \
205     sizeof(struct_elements)/sizeof(struct_elements[0])
206 #define NUMBER_OF_MEMBER_ELEMENTS \
207     sizeof(member_elements)/sizeof(member_elements[0])
208 #define NUMBER_OF_ARRAY_ELEMENTS \
209     sizeof(array_elements)/sizeof(array_elements[0])
210 #define NUMBER_OF_DATA_ELEMENTS \
211     sizeof(data_elements)/sizeof(data_elements[0])
212 #define NUMBER_OF_FAULT_ELEMENTS \
213     sizeof(fault_elements)/sizeof(fault_elements[0])
214 
215 
216 /* --------------------------------------
217  * internal parser function declarations
218  */
219 
220 static int parse_document(xmlDocPtr document, XMLRPCDocument *xrdoc);
221 static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node,
222                 XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall);
223 static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node,
224                 XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall);
225 static int parse_methodresponse(xmlDocPtr doc, xmlNodePtr node,
226                 XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse,
227                 int* n);
228 static int parse_methodresponse_element(xmlDocPtr doc, xmlNodePtr node,
229                 XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse);
230 static int parse_params(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
231                 List *params);
232 static int parse_params_element(xmlDocPtr doc, xmlNodePtr node,
233                 XMLRPCDocument *xrdoc, List *params);
234 static int parse_param(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
235                 List *params, int *n);
236 static int parse_param_element(xmlDocPtr doc, xmlNodePtr node,
237                 XMLRPCDocument *xrdoc, List *params);
238 static int parse_value(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
239                 XMLRPCValue *value);
240 static int parse_value_element(xmlDocPtr doc, xmlNodePtr node,
241                 XMLRPCDocument *xrdoc, XMLRPCValue *xrvalue);
242 static int parse_struct(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
243                 Dict *members);
244 static int parse_struct_element(xmlDocPtr doc, xmlNodePtr node,
245                 XMLRPCDocument *xrdoc, Dict *members);
246 static int parse_member(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
247                 XMLRPCMember *member);
248 static int parse_member_element(xmlDocPtr doc, xmlNodePtr node,
249                 XMLRPCDocument *xrdoc, XMLRPCMember *member);
250 static int parse_array(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
251                 List *elements);
252 static int parse_array_element(xmlDocPtr doc, xmlNodePtr node,
253                 XMLRPCDocument *xrdoc, List *elements);
254 static int parse_data(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
255                 List *elements);
256 static int parse_data_element(xmlDocPtr doc, xmlNodePtr node,
257                 XMLRPCDocument *xrdoc, List *elements);
258 static int parse_fault(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
259                 XMLRPCFault *fault);
260 static int parse_fault_element(xmlDocPtr doc, xmlNodePtr node,
261                 XMLRPCDocument *xrdoc, XMLRPCFault *fault);
262 
263 
264 /*-------------------------------------
265  * MethodCall
266  */
267 
xmlrpc_call_create(Octstr * name)268 static XMLRPCMethodCall *xmlrpc_call_create(Octstr *name)
269 {
270     XMLRPCMethodCall *nmsg = gw_malloc(sizeof(XMLRPCMethodCall));
271 
272     nmsg->method_name = octstr_duplicate(name);
273     nmsg->params = gwlist_create();
274 
275     return nmsg;
276 }
277 
xmlrpc_call_destroy(XMLRPCMethodCall * call)278 static void xmlrpc_call_destroy(XMLRPCMethodCall *call)
279 {
280     if (call == NULL)
281         return;
282 
283     octstr_destroy(call->method_name);
284     gwlist_destroy(call->params, xmlrpc_value_destroy_item);
285 
286     gw_free(call);
287 }
288 
xmlrpc_call_get_name(XMLRPCMethodCall * call)289 static Octstr *xmlrpc_call_get_name(XMLRPCMethodCall *call)
290 {
291     return call->method_name;
292 }
293 
xmlrpc_call_add_param(XMLRPCMethodCall * method,XMLRPCValue * value)294 static int xmlrpc_call_add_param(XMLRPCMethodCall *method, XMLRPCValue *value)
295 {
296     if (method == NULL || value == NULL)
297         return -1;
298 
299     gwlist_produce(method->params, value);
300     return 0;
301 }
302 
xmlrpc_call_print(XMLRPCMethodCall * call,int level)303 static Octstr *xmlrpc_call_print(XMLRPCMethodCall *call, int level)
304 {
305     Octstr *body, *os_value;
306     XMLRPCValue *val;
307     long i;
308 
309     if (call == NULL || call->method_name == NULL)
310         return NULL;
311 
312     body = octstr_format("%*s<methodCall>\n"
313                          "%*s<methodName>%S</methodName>\n",
314                          level, "", level + 2, "", call->method_name);
315 
316     gwlist_lock(call->params);
317     if (gwlist_len(call->params) > 0) {
318         octstr_format_append(body, "%*s<params>\n", level + 2, "");
319         for (i = 0; i < gwlist_len(call->params); i++) {
320             val = gwlist_get(call->params, i);
321             os_value = xmlrpc_value_print(val, level + 6);
322 
323             if (os_value == NULL) {
324                 error(0, "XMLRPC: Could not print method call, param %ld malformed", i);
325                 octstr_destroy(body);
326                 return NULL;
327             }
328             octstr_format_append(body, "%*s<param>\n%S%*s</param>\n",
329                                  level + 4, "", os_value, level + 4, "");
330             octstr_destroy(os_value);
331         }
332         octstr_format_append(body, "%*s</params>\n", level + 2, "");
333     }
334     gwlist_unlock(call->params);
335     octstr_format_append(body, "%*s</methodCall>\n", level, "");
336 
337     return body;
338 }
339 
340 
341 /*-------------------------------------
342  * XMLRPCFault
343  */
344 
xmlrpc_fault_create(long fcode,Octstr * fstring)345 static XMLRPCFault *xmlrpc_fault_create(long fcode, Octstr *fstring)
346 {
347     XMLRPCFault *fault = gw_malloc(sizeof(XMLRPCFault));
348 
349     fault->f_code = fcode;
350     fault->f_string = octstr_duplicate(fstring);
351 
352     return fault;
353 }
354 
xmlrpc_fault_destroy(XMLRPCFault * fault)355 static void xmlrpc_fault_destroy(XMLRPCFault *fault)
356 {
357     if (fault == NULL) return;
358 
359     octstr_destroy(fault->f_string);
360     gw_free(fault);
361 }
362 
xmlrpc_fault_get_code(XMLRPCFault * fault)363 static long xmlrpc_fault_get_code(XMLRPCFault *fault)
364 {
365     if (fault == NULL) return -1;
366 
367     return fault->f_code;
368 }
369 
xmlrpc_fault_get_string(XMLRPCFault * fault)370 static Octstr *xmlrpc_fault_get_string(XMLRPCFault *fault)
371 {
372     if (fault == NULL) return NULL;
373 
374     return fault->f_string;
375 }
376 
xmlrpc_fault_print(XMLRPCFault * fault,int level)377 static Octstr *xmlrpc_fault_print(XMLRPCFault *fault, int level)
378 {
379     Octstr *os;
380 
381     if (fault == NULL) return NULL;
382 
383     os = octstr_format("%*s<fault>\n%*s<value>\n"
384                          "%*s<struct>\n"
385                            "%*s<member>\n"
386                              "%*s<name>faultCode</name>\n"
387                              "%*s<value><int>%ld</int></value>\n"
388                            "%*s</member>\n"
389                            "%*s<member>\n"
390                              "%*s<name>faultString</name>\n"
391                              "%*s<value><string>%S</string></value>\n"
392                            "%*s</member>\n"
393                            "%*s</struct>\n"
394                        "%*s</value>\n%*s</fault>\n",
395                        level, "", level+2, "", level+4, "", level+6, "",
396                        level+8, "", level+8, "",
397                        fault->f_code,
398                        level+6, "", level+6, "", level+8, "", level+8, "",
399                        (fault->f_string == NULL ? octstr_imm("/") : fault->f_string),
400                        level+6, "", level+4, "", level+2, "", level, "");
401 
402     return os;
403 }
404 
405 
406 /*-------------------------------------
407  * MethodResponse
408  */
409 
410 
xmlrpc_response_create(void)411 static XMLRPCMethodResponse *xmlrpc_response_create(void)
412 {
413     XMLRPCMethodResponse *nmsg = gw_malloc(sizeof(XMLRPCMethodResponse));
414 
415     nmsg->param = NULL;
416     nmsg->fault = NULL;
417 
418     return nmsg;
419 }
420 
xmlrpc_response_destroy(XMLRPCMethodResponse * response)421 static void xmlrpc_response_destroy(XMLRPCMethodResponse *response)
422 {
423     if (response == NULL)
424         return;
425 
426     xmlrpc_value_destroy(response->param);
427     xmlrpc_fault_destroy(response->fault);
428 
429     gw_free(response);
430 }
431 
xmlrpc_response_add_param(XMLRPCMethodResponse * response,XMLRPCValue * value)432 static int xmlrpc_response_add_param(XMLRPCMethodResponse *response, XMLRPCValue *value)
433 {
434     if (response == NULL || value == NULL)
435         return -1;
436 
437     if (response->param != NULL) {
438         error(0, "XMLRPC: Method Response may contain only one param.");
439         return -1;
440     }
441     if (response->fault != NULL) {
442         error(0, "XMLRPC: Fault Response may not contain any param.");
443         return -1;
444     }
445 
446     response->param = value;
447     return 0;
448 }
449 
xmlrpc_response_is_fault(XMLRPCMethodResponse * response)450 static int xmlrpc_response_is_fault(XMLRPCMethodResponse *response)
451 {
452     if (response == NULL || response->fault == NULL)
453         return 0;
454 
455     return 1;
456 }
457 
xmlrpc_response_get_faultcode(XMLRPCMethodResponse * faultresponse)458 static long xmlrpc_response_get_faultcode(XMLRPCMethodResponse *faultresponse)
459 {
460     if (! xmlrpc_response_is_fault(faultresponse)) {
461         error(0, "XMLRPC response is not fault response.");
462         return -1;
463     }
464 
465     return xmlrpc_fault_get_code(faultresponse->fault);
466 }
467 
xmlrpc_response_get_faultstring(XMLRPCMethodResponse * faultresponse)468 static Octstr *xmlrpc_response_get_faultstring(XMLRPCMethodResponse *faultresponse)
469 {
470     if (! xmlrpc_response_is_fault(faultresponse)) {
471         error(0, "XMLRPC response is not fault response.");
472         return NULL;
473     }
474 
475     return xmlrpc_fault_get_string(faultresponse->fault);
476 }
477 
478 
xmlrpc_response_print(XMLRPCMethodResponse * response,int level)479 static Octstr *xmlrpc_response_print(XMLRPCMethodResponse *response, int level)
480 {
481     Octstr *body = NULL, *os_value = NULL;
482 
483     if (response->fault == NULL && response->param != NULL) {
484         os_value = xmlrpc_value_print(response->param, level + 6);
485 
486         body = octstr_format("%*s<methodResponse>\n"
487                              "%*s<params>\n%*s<param>\n"
488                              "%S"
489                              "%*s</param>\n%*s</params>\n"
490                              "%*s</methodResponse>\n",
491                              level, "", level+2, "", level+4, "", os_value,
492                              level+4, "", level+2, "", level, "");
493     }
494     else if (response->fault != NULL && response->param == NULL) {
495         os_value = xmlrpc_fault_print(response->fault, level + 2);
496 
497         body = octstr_format("%*s<methodResponse>\n"
498                              "%S"
499                              "%*s</methodResponse>\n",
500                              level, "", os_value, level, "");
501     }
502 
503     octstr_destroy(os_value);
504     return body;
505 }
506 
507 
508 /*-------------------------------------
509  * Document
510  */
511 
xmlrpc_doc_create(void)512 XMLRPCDocument *xmlrpc_doc_create(void)
513 {
514     XMLRPCDocument *xrdoc = gw_malloc(sizeof(XMLRPCDocument));
515 
516     xrdoc->d_type = xr_undefined;
517     xrdoc->parse_status = XMLRPC_COMPILE_OK;
518     xrdoc->parse_error = NULL;
519     xrdoc->methodcall = NULL;
520     xrdoc->methodresponse = NULL;
521 
522     return xrdoc;
523 }
524 
xmlrpc_doc_create_call(Octstr * name)525 XMLRPCDocument *xmlrpc_doc_create_call(Octstr *name)
526 {
527     XMLRPCDocument *xrdoc;
528 
529     xrdoc = xmlrpc_doc_create();
530     xrdoc->d_type = xr_methodcall;
531     xrdoc->methodcall = xmlrpc_call_create(name);
532 
533     return xrdoc;
534 }
535 
xmlrpc_doc_create_response(void)536 XMLRPCDocument *xmlrpc_doc_create_response(void)
537 {
538     XMLRPCDocument *xrdoc;
539 
540     xrdoc = xmlrpc_doc_create();
541     xrdoc->d_type = xr_methodresponse;
542     xrdoc->methodresponse = xmlrpc_response_create();
543 
544     return xrdoc;
545 }
546 
xmlrpc_doc_create_faultresponse(long faultcode,Octstr * faultstring)547 XMLRPCDocument *xmlrpc_doc_create_faultresponse(long faultcode, Octstr *faultstring)
548 {
549     XMLRPCDocument *xrdoc;
550     XMLRPCMethodResponse *response;
551 
552     xrdoc = xmlrpc_doc_create_response();
553 
554     response = xrdoc->methodresponse;
555     response->fault = xmlrpc_fault_create(faultcode, faultstring);
556 
557     return xrdoc;
558 }
559 
xmlrpc_doc_parse(Octstr * post_body,int d_type)560 XMLRPCDocument *xmlrpc_doc_parse(Octstr *post_body, int d_type)
561 {
562     XMLRPCDocument *xrdoc = xmlrpc_doc_create();
563     xmlDocPtr pDoc;
564     size_t size;
565     char *body;
566 
567     if (post_body == NULL) {
568         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
569         xrdoc->parse_error = octstr_create("XMLRPC: (null) XML document given.");
570         return xrdoc;
571     }
572     xrdoc->d_type = d_type;
573 
574     octstr_strip_blanks(post_body);
575     octstr_shrink_blanks(post_body);
576     size = octstr_len(post_body);
577     body = octstr_get_cstr(post_body);
578 
579     /* parse XML document to a XML tree */
580     pDoc = xmlParseMemory(body, size);
581     if (!pDoc) {
582         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
583         xrdoc->parse_error = octstr_create("XMLRPC: not valid XML document given.");
584         return xrdoc;
585     }
586     parse_document(pDoc, xrdoc);
587     xmlFreeDoc(pDoc);
588 
589     return xrdoc;
590 }
591 
592 /* Destroy XMLRPCDocument object */
xmlrpc_doc_destroy(XMLRPCDocument * xrdoc,int d_type)593 void xmlrpc_doc_destroy(XMLRPCDocument *xrdoc, int d_type)
594 {
595     if (xrdoc == NULL)
596         return;
597 
598     if (xrdoc->d_type != d_type)
599         warning(0, "Destroying document with different type then given.");
600 
601     xmlrpc_call_destroy(xrdoc->methodcall);
602     xmlrpc_response_destroy(xrdoc->methodresponse);
603     octstr_destroy(xrdoc->parse_error);
604 
605     gw_free(xrdoc);
606 }
607 
608 /* Add given <value> param to XMLRPCDocument object.
609  * Return 0 if ok or -1 if something wrong (e.g. xrdoc is null or faultresponse)
610  */
xmlrpc_doc_add_value(XMLRPCDocument * xrdoc,int d_type,XMLRPCValue * value)611 int xmlrpc_doc_add_value(XMLRPCDocument *xrdoc, int d_type, XMLRPCValue *value)
612 {
613     if (xrdoc == NULL)
614         return -1;
615 
616     if (xrdoc->d_type != d_type && d_type != xr_undefined) {
617         error(0, "Wrong xmlrpc document type. Param not added.");
618         return -1;
619     }
620     if (xrdoc->d_type == xr_methodresponse) {
621         if (xmlrpc_response_add_param(xrdoc->methodresponse, value) < 0)
622             return -1;
623     }
624     else if (xrdoc->d_type == xr_methodcall) {
625         if (xmlrpc_call_add_param(xrdoc->methodcall, value) < 0)
626             return -1;
627     }
628     else {
629         error(0, "Unknown xmlrpc document type. Param not added.");
630         return -1;
631     }
632     return 0;
633 }
634 
635 /* Add a scalar param to MethodCall/MethodResponse.
636  * Return 0 if ok or -1 if something wrong (e.g. xrdoc is null or faultresponse)
637  */
xmlrpc_doc_add_scalar(XMLRPCDocument * xrdoc,int d_type,int type,void * arg)638 int xmlrpc_doc_add_scalar(XMLRPCDocument *xrdoc, int d_type, int type, void *arg)
639 {
640     XMLRPCValue *param;
641 
642     param = xmlrpc_create_scalar_value(type, arg);
643     if (xmlrpc_doc_add_value(xrdoc, d_type, param) < 0) {
644         xmlrpc_value_destroy(param);
645         return -1;
646     }
647     return 0;
648 }
649 
650 
651 /* Create Octstr (text/xml string) out of given XMLRPCDocument. Caller
652  * must free returned Octstr */
xmlrpc_doc_print(XMLRPCDocument * xrdoc,int d_type,int level)653 Octstr *xmlrpc_doc_print(XMLRPCDocument *xrdoc, int d_type, int level)
654 {
655     Octstr *body = NULL, *pref = NULL;
656 
657     if (xrdoc == NULL)
658         return NULL;
659 
660     if (xrdoc->d_type != d_type) {
661         error(0, "Wrong xmlrpc document type.");
662         return NULL;
663     }
664     if (xrdoc->d_type == xr_methodresponse) {
665         body = xmlrpc_response_print(xrdoc->methodresponse, level);
666     }
667     else if (xrdoc->d_type == xr_methodcall) {
668         body = xmlrpc_call_print(xrdoc->methodcall, level);
669     }
670     else {
671         error(0, "Unknown xmlrpc document type.");
672     }
673 
674     if (body != NULL) {
675         pref = octstr_format("%*s<?xml version=\"1.0\"?>\n", level, "");
676         octstr_insert(body, pref, 0);
677         octstr_destroy(pref);
678     }
679     return body;
680 }
681 
682 /* Send XMLRPCDocument to given URL with given Headers.
683  * Return 0 if all went fine, -1 if failure. As user reference, uses *void
684  */
xmlrpc_doc_send(XMLRPCDocument * xrdoc,int d_type,HTTPCaller * http_ref,Octstr * url,List * headers,void * ref)685 int xmlrpc_doc_send(XMLRPCDocument *xrdoc, int d_type, HTTPCaller *http_ref,
686                     Octstr *url, List *headers, void *ref)
687 {
688     Octstr *body;
689     if (http_ref == NULL || xrdoc == NULL)
690         return -1;
691 
692     if (xrdoc->d_type != d_type) {
693         error(0, "Wrong xmlrpc document type.");
694         return -1;
695     }
696 
697     if (headers == NULL)
698         headers = gwlist_create();
699 
700     http_header_remove_all(headers, "Content-Type");
701     http_header_add(headers, "Content-Type", "text/xml");
702 
703     /*
704      * XML-RPC specs say we at least need Host and User-Agent
705      * HTTP headers to be defined.
706      * These are set anyway within gwlib/http.c:build_request()
707      */
708     body = xmlrpc_doc_print(xrdoc, d_type, 0);
709 
710     http_start_request(http_ref, HTTP_METHOD_POST,
711                        url, headers, body, 0, ref, NULL);
712 
713     octstr_destroy(body);
714     /* XXX: should headers be destroyed here? */
715     /*http_destroy_headers(headers); */
716     return 0;
717 }
718 
719 
720 /*-------------------------------------
721  * XMLRPCValue
722  */
723 
724 
725 /* Create new value. Set type of it to xr_undefined, so it must be
726  * set laterwards to correct one
727  */
xmlrpc_value_create(void)728 XMLRPCValue *xmlrpc_value_create(void)
729 {
730     XMLRPCValue *val = gw_malloc(sizeof(XMLRPCValue));
731 
732     val->v_type = xr_undefined;
733     val->v_scalar = NULL;
734     val->v_array = NULL;
735     val->v_struct = NULL;
736     return val;
737 }
738 
739 /* Destroy value with its information, recursively if need to */
xmlrpc_value_destroy(XMLRPCValue * val)740 void xmlrpc_value_destroy(XMLRPCValue *val)
741 {
742     if (val == NULL)
743         return;
744 
745     switch(val->v_type) {
746         case xr_scalar:
747             xmlrpc_scalar_destroy(val->v_scalar);
748             break;
749         case xr_array:
750             gwlist_destroy(val->v_array, xmlrpc_value_destroy_item);
751             break;
752         case xr_struct:
753             dict_destroy(val->v_struct);
754             break;
755     }
756     gw_free(val);
757 }
758 
759 /* wrapper to destroy to be used with list */
xmlrpc_value_destroy_item(void * val)760 void xmlrpc_value_destroy_item(void *val)
761 {
762     xmlrpc_value_destroy(val);
763 }
764 
xmlrpc_value_set_type(XMLRPCValue * val,int v_type)765 int xmlrpc_value_set_type(XMLRPCValue *val, int v_type)
766 {
767     if (val == NULL)
768         return -1;
769 
770     switch(v_type) {
771         case xr_scalar:
772         case xr_array:
773         case xr_struct:
774             val->v_type = v_type;
775             break;
776         default:
777             error(0, "XMLRPC: value type not supported.");
778             return -1;
779     }
780 
781     return 0;
782 }
783 
xmlrpc_value_set_content(XMLRPCValue * val,void * content)784 int xmlrpc_value_set_content(XMLRPCValue *val, void *content)
785 {
786     if (val == NULL)
787         return -1;
788 
789     switch(val->v_type) {
790         case xr_scalar:
791             val->v_scalar = (XMLRPCScalar *)content;
792             break;
793         case xr_array:
794             val->v_array  = (List *)content;
795             break;
796         case xr_struct:
797             val->v_struct = (Dict *)content;
798             break;
799         default:
800             error(0, "XMLRPC: value type not supported.");
801             return -1;
802     }
803 
804     return 0;
805 }
806 
xmlrpc_value_get_type(XMLRPCValue * val)807 int xmlrpc_value_get_type(XMLRPCValue *val)
808 {
809     if (val == NULL)
810         return -1;
811 
812     return val->v_type;
813 }
814 
xmlrpc_value_get_type_smart(XMLRPCValue * val)815 int xmlrpc_value_get_type_smart(XMLRPCValue *val)
816 {
817     int type = xmlrpc_value_get_type(val);
818     if (type == xr_scalar)
819         return xmlrpc_get_scalar_value_type(val);
820 
821     return type;
822 }
823 
xmlrpc_value_get_content(XMLRPCValue * val)824 void *xmlrpc_value_get_content(XMLRPCValue *val)
825 {
826     if (val == NULL)
827         return NULL;
828 
829     switch(val->v_type) {
830         case xr_scalar:
831             return val->v_scalar;
832         case xr_array:
833             return val->v_array;
834         case xr_struct:
835             return val->v_struct;
836         default:
837             error(0, "XMLRPC: value type not supported.");
838             return NULL;
839     }
840 }
841 
xmlrpc_value_print(XMLRPCValue * val,int level)842 Octstr *xmlrpc_value_print(XMLRPCValue *val, int level)
843 {
844     Octstr *body = NULL, *os = NULL;
845 
846     if (val == NULL)
847         return NULL;
848 
849     switch(val->v_type) {
850         case xr_scalar:
851             os = xmlrpc_scalar_print(val->v_scalar, level+2);
852            break;
853         case xr_struct:
854             os = xmlrpc_print_struct(val->v_struct, level+2);
855             break;
856         case xr_array:
857             os = xmlrpc_print_array(val->v_array, level+2);
858             break;
859         default:
860             return NULL;
861     }
862 
863     if (os != NULL) {
864         body = octstr_format("%*s<value>\n%S%*s</value>\n",
865                              level, "", os, level, "");
866         octstr_destroy(os);
867     }
868 
869     return body;
870 }
871 
872 
873 /*-------------------------------------
874  * XMLRPCScalar
875  */
876 
877 
878 /* Create new scalar of given type with given argument */
xmlrpc_scalar_create(int type,void * arg)879 XMLRPCScalar *xmlrpc_scalar_create(int type, void *arg)
880 {
881     XMLRPCScalar *scalar = gw_malloc(sizeof(XMLRPCScalar));
882 
883     scalar->s_type = type;
884     scalar->s_int = 0;
885     scalar->s_bool = 0;
886     scalar->s_double = 0.0;
887     scalar->s_str = NULL;
888     scalar->s_date = NULL;
889     scalar->s_base64 = NULL;
890 
891     if (arg == NULL) {
892 #ifdef XR_ENABLE_EMPTY_STRING_VALUES
893         if (scalar->s_type != xr_string) {
894 #endif
895             error(0,"XML-RPC: scalar value may not be null!");
896             xmlrpc_scalar_destroy(scalar);
897             return NULL;
898 #ifdef XR_ENABLE_EMPTY_STRING_VALUES
899         }
900 #endif
901     }
902     switch (type) {
903         case xr_int:
904             if (arg != NULL)
905                 scalar->s_int = *(long*)arg;
906             break;
907         case xr_bool:
908             if (arg != NULL)
909                 scalar->s_bool = *(int*)arg;
910             break;
911         case xr_double:
912             if (arg != NULL)
913                 scalar->s_double = *(double*)arg;
914             break;
915         case xr_string:
916             scalar->s_str = octstr_duplicate((Octstr *)arg);
917             break;
918         case xr_date:
919             scalar->s_date = octstr_duplicate((Octstr *)arg);
920             break;
921         case xr_base64:
922             scalar->s_base64 = octstr_duplicate((Octstr *)arg);
923             break;
924         default:
925             error(0,"XML-RPC: scalar type not supported!");
926             xmlrpc_scalar_destroy(scalar);
927             return NULL;
928     }
929     return scalar;
930 }
931 
932 
933 /* Destroy scalar */
xmlrpc_scalar_destroy(XMLRPCScalar * scalar)934 void xmlrpc_scalar_destroy(XMLRPCScalar *scalar)
935 {
936     if (scalar == NULL)
937         return;
938 
939     octstr_destroy(scalar->s_str);
940     octstr_destroy(scalar->s_date);
941     octstr_destroy(scalar->s_base64);
942 
943     gw_free(scalar);
944 }
945 
xmlrpc_scalar_get_type(XMLRPCScalar * scalar)946 int xmlrpc_scalar_get_type(XMLRPCScalar *scalar)
947 {
948     if (scalar == NULL)
949         return -1;
950     return scalar->s_type;
951 }
952 
xmlrpc_scalar_get_content(XMLRPCScalar * scalar,int s_type)953 void *xmlrpc_scalar_get_content(XMLRPCScalar *scalar, int s_type)
954 {
955     if (scalar == NULL)
956         return NULL;
957     if (scalar->s_type != s_type) {
958         error(0, "XMLRPC: Scalar content request with bogus type");
959         return NULL;
960     }
961     switch (scalar->s_type) {
962         case xr_int:     return &(scalar->s_int);
963         case xr_bool:    return &(scalar->s_bool);
964         case xr_double:  return &(scalar->s_double);
965         case xr_string:  return scalar->s_str;
966         case xr_date:    return scalar->s_date;
967         case xr_base64:  return scalar->s_base64;
968         default:
969             error(0,"XML-RPC: scalar type not supported!");
970             return NULL;
971     }
972 }
973 
xmlrpc_scalar_print(XMLRPCScalar * scalar,int level)974 Octstr *xmlrpc_scalar_print(XMLRPCScalar *scalar, int level)
975 {
976     Octstr *os = NULL;
977 
978     if (scalar == NULL)
979         return NULL;
980 
981     switch (scalar->s_type) {
982         case xr_int:
983             os = octstr_format("%*s<int>%ld</int>\n",
984                                level, "", scalar->s_int);
985             break;
986         case xr_bool:
987             os = octstr_format("%*s<bool>%d</bool>\n",
988                                level, "", scalar->s_bool);
989             break;
990         case xr_double:
991             os = octstr_format("%*s<double>%d</double>\n",
992                                  level, "", scalar->s_double);
993             break;
994         case xr_string:
995             if (scalar->s_str == NULL) {
996 #ifdef XR_ENABLE_EMPTY_STRING_VALUES
997                 os = octstr_format("%*s<string></string>\n",
998                                    level, "");
999 #endif
1000             } else {
1001                 Octstr *tmp = octstr_duplicate(scalar->s_str);
1002                 octstr_convert_to_html_entities(tmp);
1003                 os = octstr_format("%*s<string>%S</string>\n",
1004                                    level, "", tmp);
1005                 octstr_destroy(tmp);
1006             }
1007             break;
1008         case xr_date:
1009             os = octstr_format("%*s<datetime.iso8601>%S</datetime.iso8601>\n",
1010                                level, "", scalar->s_date);
1011             break;
1012         case xr_base64:
1013             os = octstr_format("%*s<base64>%S</base64>\n",
1014                                level, "", scalar->s_base64);
1015             break;
1016     }
1017     return os;
1018 }
1019 
1020 
1021 /*-------------------------------------
1022  * XMLRPCMember - internal functions
1023  */
1024 
1025 /* Create new member with undefined name and value */
xmlrpc_member_create(void)1026 static XMLRPCMember *xmlrpc_member_create(void)
1027 {
1028     XMLRPCMember *member = gw_malloc(sizeof(XMLRPCMember));
1029 
1030     member->name = NULL;
1031     member->value = NULL;
1032 
1033     return member;
1034 }
1035 
1036 /* Destroy member and if destroy_value != 0 destroy its content */
xmlrpc_member_destroy(XMLRPCMember * member,int destroy_value)1037 static void xmlrpc_member_destroy(XMLRPCMember *member, int destroy_value)
1038 {
1039     if (member == NULL)
1040         return;
1041 
1042     octstr_destroy(member->name);
1043     if (destroy_value == 1)
1044         xmlrpc_value_destroy(member->value);
1045 
1046     gw_free(member);
1047 }
1048 
1049 
1050 
1051 /*-------------------------------------------------
1052  * Utilities to make things easier
1053  */
1054 
xmlrpc_get_call_name(XMLRPCDocument * call)1055 Octstr *xmlrpc_get_call_name(XMLRPCDocument *call)
1056 {
1057     if (call == NULL || call->methodcall == NULL)
1058         return NULL;
1059     return xmlrpc_call_get_name(call->methodcall);
1060 }
1061 
1062 /*** PARAMS HANDLING ***/
xmlrpc_count_params(XMLRPCDocument * xrdoc)1063 int xmlrpc_count_params(XMLRPCDocument *xrdoc)
1064 {
1065     if (xrdoc == NULL)
1066         return -1;
1067     if (xrdoc->d_type == xr_methodcall && xrdoc->methodcall != NULL)
1068         return gwlist_len(xrdoc->methodcall->params);
1069     else if (xrdoc->d_type == xr_methodresponse && xrdoc->methodresponse != NULL)
1070         return (xrdoc->methodresponse->param != NULL ? 1 : 0);
1071 
1072     return -1;
1073 }
1074 
xmlrpc_get_param(XMLRPCDocument * xrdoc,int i)1075 XMLRPCValue *xmlrpc_get_param(XMLRPCDocument *xrdoc, int i)
1076 {
1077     if (xrdoc == NULL)
1078         return NULL;
1079     if (xrdoc->d_type == xr_methodcall && xrdoc->methodcall != NULL)
1080         return gwlist_len(xrdoc->methodcall->params) > i ? gwlist_get(xrdoc->methodcall->params, i) : NULL;
1081     else if (xrdoc->d_type == xr_methodresponse && xrdoc->methodresponse != NULL
1082              && i == 0)
1083         return xrdoc->methodresponse->param;
1084 
1085     return NULL;
1086 }
1087 
xmlrpc_get_type_param(XMLRPCDocument * xrdoc,int i)1088 int xmlrpc_get_type_param(XMLRPCDocument *xrdoc, int i)
1089 {
1090     XMLRPCValue *param = xmlrpc_get_param(xrdoc, i);
1091 
1092     return xmlrpc_value_get_type(param);
1093 }
1094 
xmlrpc_get_content_param(XMLRPCDocument * xrdoc,int i)1095 void *xmlrpc_get_content_param(XMLRPCDocument *xrdoc, int i)
1096 {
1097     XMLRPCValue *param = xmlrpc_get_param(xrdoc, i);
1098 
1099     return xmlrpc_value_get_content(param);
1100 }
1101 
1102 /*** STRUCT VALUE HANDLING ***/
xmlrpc_create_struct_value(int count_members)1103 XMLRPCValue *xmlrpc_create_struct_value(int count_members)
1104 {
1105     XMLRPCValue *value = xmlrpc_value_create();
1106     int len = (count_members > 0 ? count_members : OPTIMAL_STRUCT_SIZE);
1107     value->v_type = xr_struct;
1108     value->v_struct = dict_create(len, xmlrpc_value_destroy_item);
1109 
1110     return value;
1111 }
1112 
xmlrpc_count_members(XMLRPCValue * xrstruct)1113 long xmlrpc_count_members(XMLRPCValue *xrstruct)
1114 {
1115     if (xrstruct == NULL || xrstruct->v_type != xr_struct)
1116         return -1;
1117     return dict_key_count(xrstruct->v_struct);
1118 }
1119 
xmlrpc_add_member(XMLRPCValue * xrstruct,Octstr * name,XMLRPCValue * value)1120 int xmlrpc_add_member(XMLRPCValue *xrstruct, Octstr *name, XMLRPCValue *value)
1121 {
1122     if (xrstruct == NULL || xrstruct->v_type != xr_struct
1123         || name == NULL || value == NULL)
1124         return -1;
1125 
1126     return dict_put_once(xrstruct->v_struct, name, value);
1127 }
1128 
xmlrpc_add_member_scalar(XMLRPCValue * xrstruct,Octstr * name,int type,void * arg)1129 int xmlrpc_add_member_scalar(XMLRPCValue *xrstruct, Octstr *name, int type, void *arg)
1130 {
1131     XMLRPCValue *value = xmlrpc_create_scalar_value(type, arg);
1132     int status;
1133 
1134     status = xmlrpc_add_member(xrstruct, name, value);
1135     if (status < 0)
1136         xmlrpc_value_destroy(value);
1137 
1138     return status;
1139 }
1140 
xmlrpc_get_member(XMLRPCValue * xrstruct,Octstr * name)1141 XMLRPCValue *xmlrpc_get_member(XMLRPCValue *xrstruct, Octstr *name)
1142 {
1143     if (xrstruct == NULL || xrstruct->v_type != xr_struct || name == NULL)
1144         return NULL;
1145 
1146     return dict_get(xrstruct->v_struct, name);
1147 }
1148 
xmlrpc_get_member_type(XMLRPCValue * xrstruct,Octstr * name)1149 int xmlrpc_get_member_type(XMLRPCValue *xrstruct, Octstr *name)
1150 {
1151     XMLRPCValue *value = xmlrpc_get_member(xrstruct, name);
1152 
1153     return xmlrpc_value_get_type(value);
1154 }
1155 
xmlrpc_get_member_content(XMLRPCValue * xrstruct,Octstr * name)1156 void *xmlrpc_get_member_content(XMLRPCValue *xrstruct, Octstr *name)
1157 {
1158     XMLRPCValue *value = xmlrpc_get_member(xrstruct, name);
1159 
1160     return xmlrpc_value_get_content(value);
1161 }
1162 
xmlrpc_print_struct(Dict * v_struct,int level)1163 Octstr *xmlrpc_print_struct(Dict *v_struct,  int level)
1164 {
1165     Octstr *body, *os_val, *key;
1166     List *keys;
1167     XMLRPCValue *member_val;
1168 
1169     if (v_struct == NULL || dict_key_count(v_struct) == 0)
1170         return NULL;
1171 
1172     keys = dict_keys(v_struct);
1173     body = octstr_format("%*s<struct>\n", level, "");
1174 
1175     while ((key = gwlist_consume(keys)) != NULL) {
1176         member_val = dict_get(v_struct, key);
1177         os_val = xmlrpc_value_print(member_val, level+4);
1178         if (os_val == NULL) {
1179             gwlist_destroy(keys, octstr_destroy_item);
1180             octstr_destroy(key);
1181             octstr_destroy(body);
1182             return NULL;
1183         }
1184         octstr_format_append(body, "%*s<member>\n"
1185                                      "%*s<name>%S</name>\n%S"
1186                                    "%*s</member>\n",
1187                                    level+2, "", level+4, "",
1188                                    key, os_val,
1189                                    level+2, "");
1190         octstr_destroy(key);
1191         octstr_destroy(os_val);
1192     }
1193     gwlist_destroy(keys, octstr_destroy_item);
1194     octstr_format_append(body, "%*s</struct>\n", level, "");
1195 
1196     return body;
1197 }
1198 
1199 /*** ARRAY VALUE HANDLING ***/
xmlrpc_create_array_value(void)1200 XMLRPCValue *xmlrpc_create_array_value(void)
1201 {
1202     XMLRPCValue *value = xmlrpc_value_create();
1203     value->v_type = xr_array;
1204     value->v_array = gwlist_create();
1205 
1206     return value;
1207 }
1208 
xmlrpc_count_elements(XMLRPCValue * xrarray)1209 int xmlrpc_count_elements(XMLRPCValue *xrarray)
1210 {
1211     if (xrarray == NULL || xrarray->v_type != xr_array)
1212         return -1;
1213 
1214     return  gwlist_len(xrarray->v_array);
1215 }
1216 
xmlrpc_add_element(XMLRPCValue * xrarray,XMLRPCValue * value)1217 int xmlrpc_add_element(XMLRPCValue *xrarray, XMLRPCValue *value)
1218 {
1219     if (xrarray == NULL || xrarray->v_type != xr_array || value == NULL)
1220         return -1;
1221 
1222     gwlist_produce(xrarray->v_array, value);
1223     return 1;
1224 }
1225 
xmlrpc_add_element_scalar(XMLRPCValue * xrarray,int type,void * arg)1226 int xmlrpc_add_element_scalar(XMLRPCValue *xrarray, int type, void *arg)
1227 {
1228     XMLRPCValue *value = xmlrpc_create_scalar_value(type, arg);
1229     int status;
1230 
1231     status = xmlrpc_add_element(xrarray, value);
1232     if (status < 0)
1233         xmlrpc_value_destroy(value);
1234 
1235     return status;
1236 }
1237 
xmlrpc_get_element(XMLRPCValue * xrarray,int i)1238 XMLRPCValue *xmlrpc_get_element(XMLRPCValue *xrarray, int i)
1239 {
1240     if (xrarray == NULL || xrarray->v_type != xr_array || i < 0)
1241         return NULL;
1242 
1243     return gwlist_get(xrarray->v_array, i);
1244 }
1245 
xmlrpc_get_element_type(XMLRPCValue * xrarray,int i)1246 int xmlrpc_get_element_type(XMLRPCValue *xrarray, int i)
1247 {
1248     XMLRPCValue *value = xmlrpc_get_element(xrarray, i);
1249 
1250     return xmlrpc_value_get_type(value);
1251 }
1252 
xmlrpc_get_element_content(XMLRPCValue * xrarray,int i)1253 void *xmlrpc_get_element_content(XMLRPCValue *xrarray, int i)
1254 {
1255     XMLRPCValue *value = xmlrpc_get_element(xrarray, i);
1256 
1257     return xmlrpc_value_get_content(value);
1258 }
1259 
xmlrpc_print_array(List * v_array,int level)1260 Octstr *xmlrpc_print_array(List *v_array,  int level)
1261 {
1262     Octstr *body, *os_element;
1263     XMLRPCValue *element = NULL;
1264     int i;
1265 
1266     if (v_array == NULL)
1267         return NULL;
1268 
1269     body = octstr_format("%*s<array>\n%*s<data>\n", level, "", level+2, "");
1270 
1271     for(i = 0; i < gwlist_len(v_array); i++) {
1272         element = gwlist_get(v_array, i);
1273         os_element = xmlrpc_value_print(element, level+4);
1274         if (os_element == NULL) {
1275             octstr_destroy(body);
1276             return NULL;
1277         }
1278 
1279         octstr_append(body, os_element);
1280         octstr_destroy(os_element);
1281     }
1282     octstr_format_append(body, "%*s</data>\n%*s</array>\n",
1283                          level+2, "", level, "");
1284 
1285     return body;
1286 }
1287 
1288 
1289 /*** SCALAR VALUE HANDLING ***/
xmlrpc_create_scalar_value(int type,void * arg)1290 XMLRPCValue *xmlrpc_create_scalar_value(int type, void *arg)
1291 {
1292     XMLRPCValue *value = xmlrpc_value_create();
1293     value->v_type = xr_scalar;
1294     value->v_scalar = xmlrpc_scalar_create(type, arg);
1295 
1296     return value;
1297 }
1298 
xmlrpc_create_double_value(double val)1299 XMLRPCValue *xmlrpc_create_double_value(double val)
1300 {
1301     return xmlrpc_create_scalar_value(xr_double, &val);
1302 }
1303 
xmlrpc_create_int_value(long val)1304 XMLRPCValue *xmlrpc_create_int_value(long val)
1305 {
1306     return xmlrpc_create_scalar_value(xr_int, &val);
1307 }
1308 
xmlrpc_create_string_value(Octstr * val)1309 XMLRPCValue *xmlrpc_create_string_value(Octstr *val)
1310 {
1311     return xmlrpc_create_scalar_value(xr_string, val);
1312 }
1313 
1314 
1315 /*** FAULT HANDLING ***/
xmlrpc_is_fault(XMLRPCDocument * response)1316 int xmlrpc_is_fault(XMLRPCDocument *response)
1317 {
1318     if (response == NULL || response->d_type != xr_methodresponse)
1319         return 0;
1320 
1321     return xmlrpc_response_is_fault(response->methodresponse);
1322 }
1323 
xmlrpc_get_faultcode(XMLRPCDocument * faultresponse)1324 long xmlrpc_get_faultcode(XMLRPCDocument *faultresponse)
1325 {
1326     if (! xmlrpc_is_fault(faultresponse)) {
1327         error(0, "XMLRPC object is not fault response.");
1328         return -1;
1329     }
1330 
1331     return xmlrpc_response_get_faultcode(faultresponse->methodresponse);
1332 }
1333 
xmlrpc_get_faultstring(XMLRPCDocument * faultresponse)1334 Octstr *xmlrpc_get_faultstring(XMLRPCDocument *faultresponse)
1335 {
1336     if (! xmlrpc_is_fault(faultresponse)) {
1337         error(0, "XMLRPC object is not fault response.");
1338         return NULL;
1339     }
1340 
1341     return xmlrpc_response_get_faultstring(faultresponse->methodresponse);
1342 }
1343 
1344 
1345 /*** PARSE STATUS HANDLING***/
1346 
xmlrpc_parse_status(XMLRPCDocument * xrdoc)1347 int xmlrpc_parse_status(XMLRPCDocument *xrdoc)
1348 {
1349     if (xrdoc == NULL)
1350         return -1;
1351 
1352     return xrdoc->parse_status;
1353 }
1354 
xmlrpc_parse_error(XMLRPCDocument * xrdoc)1355 Octstr *xmlrpc_parse_error(XMLRPCDocument *xrdoc)
1356 {
1357     if (xrdoc == NULL)
1358         return NULL;
1359 
1360     return octstr_duplicate(xrdoc->parse_error);
1361 }
1362 
1363 
1364 /*-------------------------------------------------
1365  * Internal parser functions
1366  */
1367 
parse_document(xmlDocPtr document,XMLRPCDocument * xrdoc)1368 static int parse_document(xmlDocPtr document, XMLRPCDocument *xrdoc)
1369 {
1370     xmlNodePtr node;
1371     Octstr *name;
1372     int n = 0, status = 0;
1373 
1374     node = xmlDocGetRootElement(document);
1375 
1376     /*
1377      * check if this is at least a valid root element
1378      */
1379     if (node == NULL || node->name == NULL) {
1380         error(0, "XMLRPC: XML document - not valid root node!");
1381         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1382         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1383         return -1;
1384     }
1385 
1386     name = octstr_create(node->name);
1387     if (octstr_len(name) == 0) {
1388         octstr_destroy(name);
1389         return -1;
1390     }
1391     if ((xrdoc->d_type == xr_methodcall || xrdoc->d_type == xr_undefined)
1392         && octstr_case_compare(name, octstr_imm("METHODCALL")) == 0) {
1393 
1394         xrdoc->d_type = xr_methodcall;
1395         xrdoc->methodcall = xmlrpc_call_create(NULL);
1396         octstr_destroy(name);
1397 
1398         status = parse_methodcall(document, node->xmlChildrenNode, xrdoc, xrdoc->methodcall);
1399         if (status < 0) {
1400             xmlrpc_call_destroy(xrdoc->methodcall);
1401             xrdoc->methodcall = NULL;
1402             if (xrdoc->parse_status == XMLRPC_COMPILE_OK) {
1403                 xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1404                 xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1405             }
1406         }
1407         else if ((xrdoc->methodcall->method_name) == NULL) {
1408             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1409             xrdoc->parse_error = octstr_format("XML-RPC compiler: <methodName> tag expected!");
1410             status = -1;
1411         }
1412         return status;
1413     } else if ((xrdoc->d_type == xr_methodresponse || xrdoc->d_type == xr_undefined)
1414                && octstr_case_compare(name, octstr_imm("METHODRESPONSE")) == 0) {
1415 
1416         xrdoc->d_type = xr_methodresponse;
1417         xrdoc->methodresponse = xmlrpc_response_create();
1418         octstr_destroy(name);
1419 
1420         status = parse_methodresponse(document, node->xmlChildrenNode,
1421                                       xrdoc, xrdoc->methodresponse, &n);
1422         if (status < 0) {
1423             xmlrpc_response_destroy(xrdoc->methodresponse);
1424             xrdoc->methodresponse = NULL;
1425         }
1426         return status;
1427     } else {
1428         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1429         xrdoc->parse_error = octstr_format("XML-RPC compiler: wrong root element <%s>, "
1430                                            "<%s> expected!",
1431                                            octstr_get_cstr(name),
1432                                            (xrdoc->d_type == xr_methodcall ?
1433                                                "methodCall" : "methodResponse"));
1434         octstr_destroy(name);
1435         return -1;
1436     }
1437 }
1438 
parse_methodcall(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCMethodCall * methodcall)1439 static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
1440                             XMLRPCMethodCall *methodcall)
1441 {
1442     int status = 0;
1443 
1444     /* call for the parser function of the node type. */
1445     switch (node->type) {
1446 
1447         case XML_ELEMENT_NODE:
1448 
1449             status = parse_methodcall_element(doc, node, xrdoc, methodcall);
1450             break;
1451 
1452         case XML_TEXT_NODE:
1453         case XML_COMMENT_NODE:
1454         case XML_PI_NODE:
1455             /* Text nodes, comments and PIs are ignored. */
1456             break;
1457            /*
1458             * XML has also many other node types, these are not needed with
1459             * XML-RPC. Therefore they are assumed to be an error.
1460             */
1461         default:
1462             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1463             xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown XML node "
1464                                                "in the XML-RPC source.");
1465             return -1;
1466             break;
1467     }
1468 
1469     if (node->next != NULL)
1470         return parse_methodcall(doc, node->next, xrdoc, methodcall);
1471 
1472     return status;
1473 }
1474 
parse_methodcall_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCMethodCall * methodcall)1475 static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node,
1476                                     XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall)
1477 {
1478     Octstr *name;
1479     xmlChar *content_buff;
1480     size_t i;
1481 
1482     /*
1483      * check if the element is allowed at this level
1484      */
1485     if (node->name == NULL) {
1486         error(0, "XMLRPC: XML methodcall element nodes without name!");
1487         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1488         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1489         return -1;
1490     }
1491 
1492     name = octstr_create(node->name);
1493     if (octstr_len(name) == 0) {
1494         octstr_destroy(name);
1495         return -1;
1496     }
1497 
1498     i = 0;
1499     while (i < NUMBER_OF_METHODCALL_ELEMENTS) {
1500         if (octstr_case_compare(name, octstr_imm(methodcall_elements[i].name)) == 0)
1501             break;
1502         ++i;
1503     }
1504     if (i == NUMBER_OF_METHODCALL_ELEMENTS) {
1505         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1506         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' in XML source "
1507                                            "at level <methodCall>", octstr_get_cstr(name));
1508         octstr_destroy(name);
1509         return -1;
1510     }
1511     octstr_destroy(name);
1512 
1513     /*
1514      * now check which type it is and process
1515      *
1516      * valid tags at this level are:
1517      *   methodName [0]
1518      *   params     [1]
1519      */
1520     if (i == 0) {
1521         /* this has been the <methodName> tag */
1522         if (methodcall->method_name == NULL) {
1523             /*only one <methodName> tag allowed*/
1524             content_buff = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
1525             if (content_buff != NULL) {
1526                 methodcall->method_name = octstr_create(content_buff);
1527                 xmlFree(content_buff);
1528             } else {
1529                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1530                 xrdoc->parse_error = octstr_format("XML-RPC compiler: empty tag <methodName> in XML source "
1531                                            "at level <methodCall>");
1532                 return -1;
1533             }
1534         } else {
1535             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1536             xrdoc->parse_error = octstr_format("XML-RPC compiler: duplicated tag <methodName> in XML source "
1537                                                "at level <methodCall>");
1538             octstr_destroy(name);
1539             return -1;
1540         }
1541     } else {
1542         /*
1543          * ok, this has to be an <params> tag, otherwise we would
1544          * have returned previosly
1545          */
1546         return parse_params(doc, node->xmlChildrenNode, xrdoc, methodcall->params);
1547     }
1548     return 0;
1549 }
1550 
parse_methodresponse(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCMethodResponse * methodresponse,int * n)1551 static int parse_methodresponse(xmlDocPtr doc, xmlNodePtr node,
1552                             XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse, int* n)
1553 {
1554     int status = 0;
1555 
1556     /* call for the parser function of the node type. */
1557     switch (node->type) {
1558 
1559         case XML_ELEMENT_NODE:
1560             if (*n > 0) {
1561                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1562                 xrdoc->parse_error = octstr_format("XML-RPC compiler: unexpected XML node <%s> "
1563                                                    "in the XML-RPC source.", node->name);
1564                 return -1;
1565             }
1566             status = parse_methodresponse_element(doc, node, xrdoc, methodresponse);
1567             (*n)++;
1568             break;
1569 
1570         case XML_TEXT_NODE:
1571         case XML_COMMENT_NODE:
1572         case XML_PI_NODE:
1573             /* Text nodes, comments and PIs are ignored. */
1574             break;
1575            /*
1576             * XML has also many other node types, these are not needed with
1577             * XML-RPC. Therefore they are assumed to be an error.
1578             */
1579         default:
1580             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1581             xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown XML node "
1582                                                "in the XML-RPC source.");
1583             return -1;
1584             break;
1585     }
1586 
1587     if (node->next != NULL) {
1588         if (parse_methodresponse(doc, node->next, xrdoc, methodresponse, n) == -1) {
1589             return -1;
1590         }
1591     }
1592 
1593     return status;
1594 }
1595 
parse_methodresponse_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCMethodResponse * methodresponse)1596 static int parse_methodresponse_element(xmlDocPtr doc, xmlNodePtr node,
1597                                     XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse)
1598 {
1599     Octstr *name;
1600     size_t i;
1601     int status;
1602 
1603     /*
1604      * check if the element is allowed at this level
1605      */
1606     if (node->name == NULL) {
1607         error(0, "XMLRPC: XML methodResponse element nodes without name!");
1608         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1609         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1610         return -1;
1611     }
1612 
1613     name = octstr_create(node->name);
1614     if (octstr_len(name) == 0) {
1615         octstr_destroy(name);
1616         return -1;
1617     }
1618 
1619     i = 0;
1620     while (i < NUMBER_OF_METHODRESPONSE_ELEMENTS) {
1621         if (octstr_case_compare(name, octstr_imm(methodresponse_elements[i].name)) == 0)
1622             break;
1623         ++i;
1624     }
1625     if (i == NUMBER_OF_METHODRESPONSE_ELEMENTS) {
1626         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1627         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' in XML source "
1628                                            "at level <methodResponse>", octstr_get_cstr(name));
1629         octstr_destroy(name);
1630         return -1;
1631     }
1632     octstr_destroy(name);
1633 
1634     /*
1635      * now check which type it is and process
1636      *
1637      * valid tags at this level are:
1638      *   fault  [0]
1639      *   params [1]
1640      */
1641     if (i == 0) {
1642         /* this has been the <fault> tag */
1643         methodresponse->fault = xmlrpc_fault_create(0, NULL);
1644         return parse_fault(doc, node->xmlChildrenNode, xrdoc, methodresponse->fault);
1645     } else {
1646         /*
1647          * ok, this has to be an <params> tag, otherwise we would
1648          * have returned previosly
1649          */
1650         List *params = gwlist_create();;
1651         status = parse_params(doc, node->xmlChildrenNode, xrdoc, params);
1652         if (status < 0) return -1;
1653         if (gwlist_len(params) != 1) {
1654             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1655             xrdoc->parse_error = octstr_format("XML-RPC compiler:wrong number of params "
1656                                                "at level <methodResponse>");
1657             gwlist_destroy(params, xmlrpc_value_destroy_item);
1658             return -1;
1659         }
1660         methodresponse->param = gwlist_consume(params);
1661         gwlist_destroy(params, xmlrpc_value_destroy_item);
1662         return status;
1663     }
1664 
1665 }
1666 
parse_params(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * params)1667 static int parse_params(xmlDocPtr doc, xmlNodePtr node,
1668                         XMLRPCDocument *xrdoc, List *params)
1669 {
1670     int status = 0;
1671 
1672     /* call for the parser function of the node type. */
1673     switch (node->type) {
1674 
1675         case XML_ELEMENT_NODE:
1676             status = parse_params_element(doc, node, xrdoc, params);
1677             break;
1678 
1679         case XML_TEXT_NODE:
1680         case XML_COMMENT_NODE:
1681         case XML_PI_NODE:
1682             /* Text nodes, comments and PIs are ignored. */
1683             break;
1684            /*
1685             * XML has also many other node types, these are not needed with
1686             * XML-RPC. Therefore they are assumed to be an error.
1687             */
1688         default:
1689             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1690             xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown XML node in XML-RPC source.");
1691             return -1;
1692             break;
1693     }
1694 
1695     if (node->next != NULL)
1696            if (parse_params(doc, node->next, xrdoc, params) == -1)
1697             return -1;
1698 
1699     return status;
1700 }
1701 
parse_params_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * params)1702 static int parse_params_element(xmlDocPtr doc, xmlNodePtr node,
1703                                 XMLRPCDocument *xrdoc, List *params)
1704 {
1705     Octstr *name;
1706     size_t i;
1707     int n = 0;
1708 
1709     /*
1710      * check if the element is allowed at this level
1711      * within <params> we only have one or more <param>
1712      */
1713     if (node->name == NULL) {
1714         error(0, "XMLRPC: XML params element nodes without name!");
1715         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1716         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1717         return -1;
1718     }
1719 
1720     name = octstr_create(node->name);
1721     if (octstr_len(name) == 0) {
1722         octstr_destroy(name);
1723         return -1;
1724     }
1725 
1726     i = 0;
1727     while (i < NUMBER_OF_PARAMS_ELEMENTS) {
1728         if (octstr_case_compare(name, octstr_imm(params_elements[i].name)) == 0)
1729             break;
1730         ++i;
1731     }
1732     if (i == NUMBER_OF_PARAMS_ELEMENTS) {
1733         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1734         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
1735                                            "in XML source at level <params>",
1736                                            octstr_get_cstr(name));
1737         octstr_destroy(name);
1738         return -1;
1739     }
1740     octstr_destroy(name);
1741 
1742     /*
1743      * now check which type it is and process
1744      *
1745      * valid tags at this level are:
1746      *   param [0]
1747      */
1748     if (i == 0) {
1749         /* this has been a <param> tag */
1750         if (parse_param(doc, node->xmlChildrenNode, xrdoc, params, &n) == -1)
1751             return -1;
1752     } else {
1753         /* we should never be here */
1754         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1755         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_params!");
1756         return -1;
1757     }
1758     return 0;
1759 }
1760 
parse_param(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * params,int * n)1761 static int parse_param(xmlDocPtr doc, xmlNodePtr node,
1762                        XMLRPCDocument *xrdoc, List *params, int *n)
1763 {
1764     int status = 0;
1765 
1766     /* call for the parser function of the node type. */
1767     switch (node->type) {
1768 
1769         case XML_ELEMENT_NODE:
1770 
1771             /* a <param> can only have one value element type */
1772             if ((*n) > 0) {
1773                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1774                 xrdoc->parse_error = octstr_format("XML-RPC compiler: param may only have one value!");
1775                 return -1;
1776             }
1777 
1778             status = parse_param_element(doc, node, xrdoc, params);
1779             (*n)++;
1780             break;
1781 
1782         case XML_TEXT_NODE:
1783         case XML_COMMENT_NODE:
1784         case XML_PI_NODE:
1785             /* Text nodes, comments and PIs are ignored. */
1786             break;
1787            /*
1788             * XML has also many other node types, these are not needed with
1789             * XML-RPC. Therefore they are assumed to be an error.
1790             */
1791         default:
1792             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1793             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
1794             return -1;
1795             break;
1796     }
1797 
1798     if (node->next != NULL)
1799         if (parse_param(doc, node->next, xrdoc, params, n) == -1)
1800             return -1;
1801 
1802     return status;
1803 }
1804 
parse_param_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * params)1805 static int parse_param_element(xmlDocPtr doc, xmlNodePtr node,
1806                                XMLRPCDocument *xrdoc, List *params)
1807 {
1808     Octstr *name;
1809     size_t i;
1810     XMLRPCValue *value;
1811 
1812     /*
1813      * check if the element is allowed at this level
1814      */
1815     if (node->name == NULL) {
1816         error(0, "XMLRPC: XML param element nodes without name!");
1817         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1818         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1819         return -1;
1820     }
1821 
1822     name = octstr_create(node->name);
1823     if (octstr_len(name) == 0) {
1824         octstr_destroy(name);
1825         return -1;
1826     }
1827 
1828     i = 0;
1829     while (i < NUMBER_OF_PARAM_ELEMENTS) {
1830         if (octstr_case_compare(name, octstr_imm(param_elements[i].name)) == 0)
1831             break;
1832         ++i;
1833     }
1834     if (i == NUMBER_OF_PARAM_ELEMENTS) {
1835         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1836         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
1837                                            "in XML source at level <param>",
1838                                            octstr_get_cstr(name));
1839         octstr_destroy(name);
1840         return -1;
1841     }
1842     octstr_destroy(name);
1843 
1844     /*
1845      * now check which type it is and process
1846      *
1847      * valid tags at this level are:
1848      *   value [0]
1849      */
1850     if (i == 0) {
1851         /* this has been a <param> tag */
1852         value = xmlrpc_value_create();
1853         if (parse_value(doc, node->xmlChildrenNode, xrdoc, value) == -1) {
1854             xmlrpc_value_destroy(value);
1855             return -1;
1856         }
1857         gwlist_append(params, value);
1858     } else {
1859         /* we should never be here */
1860         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1861         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_param!");
1862         return -1;
1863     }
1864     return 0;
1865 }
1866 
parse_value(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCValue * value)1867 static int parse_value(xmlDocPtr doc, xmlNodePtr node,
1868                        XMLRPCDocument *xrdoc, XMLRPCValue *value)
1869 {
1870     int status = 0;
1871 
1872     /* call for the parser function of the node type. */
1873     switch (node->type) {
1874 
1875         case XML_ELEMENT_NODE:
1876             status = parse_value_element(doc, node, xrdoc, value);
1877             break;
1878 
1879         case XML_TEXT_NODE:
1880         case XML_COMMENT_NODE:
1881         case XML_PI_NODE:
1882             /* Text nodes, comments and PIs are ignored. */
1883             break;
1884            /*
1885             * XML has also many other node types, these are not needed with
1886             * XML-RPC. Therefore they are assumed to be an error.
1887             */
1888         default:
1889             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1890             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
1891             return -1;
1892             break;
1893     }
1894 
1895     if (node->next != NULL)
1896         if (parse_value(doc, node->next, xrdoc, value) == -1)
1897             return -1;
1898 
1899     return status;
1900 }
1901 
parse_value_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCValue * xrvalue)1902 static int parse_value_element(xmlDocPtr doc, xmlNodePtr node,
1903                                XMLRPCDocument *xrdoc, XMLRPCValue *xrvalue)
1904 {
1905     Octstr *name;
1906     Octstr *value = NULL;
1907     xmlChar *content_buff;
1908     long lval = 0;
1909     double dval = 0.0;
1910     size_t i;
1911 
1912     /*
1913      * check if the element is allowed at this level
1914      */
1915     if (node->name == NULL) {
1916         error(0, "XMLRPC: XML value element nodes without name!");
1917         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
1918         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
1919         return -1;
1920     }
1921 
1922     name = octstr_create(node->name);
1923     if (octstr_len(name) == 0) {
1924         octstr_destroy(name);
1925         return -1;
1926     }
1927 
1928     i = 0;
1929     while (i < NUMBER_OF_VALUE_ELEMENTS) {
1930         if (octstr_case_compare(name, octstr_imm(value_elements[i].name)) == 0)
1931             break;
1932         ++i;
1933     }
1934     if (i == NUMBER_OF_VALUE_ELEMENTS) {
1935         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1936         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
1937                                            "in XML source at level <value>",
1938                                            octstr_get_cstr(name));
1939         octstr_destroy(name);
1940         return -1;
1941     }
1942     octstr_destroy(name);
1943 
1944 
1945     content_buff = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
1946     if (content_buff != NULL) {
1947         value = octstr_create(content_buff);
1948         xmlFree(content_buff);
1949     }
1950 
1951     /*
1952      * now check which type it is and process
1953      *
1954      * valid tags at this level are:
1955      *   i4, int
1956      *   boolean
1957      *   string
1958      *   double
1959      *   dateTime.iso8601
1960      *   base64
1961      *   struct
1962      *   array
1963      */
1964     switch (value_elements[i].s_type) {
1965         /*
1966          * scalar types
1967          */
1968         case xr_int:   case xr_bool:
1969         case xr_double:
1970         case xr_date:  case xr_base64:
1971 #ifndef XR_ENABLE_EMPTY_STRING_VALUES
1972         case xr_string:
1973 #endif
1974             if (value == NULL) {
1975                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1976                 xrdoc->parse_error = octstr_format("XML-RPC compiler: no value for '%s'",
1977                                            node->name);
1978                 return -1;
1979             }
1980             break;
1981     }
1982 
1983     switch (value_elements[i].s_type) {
1984 
1985         /*
1986          * scalar types
1987          */
1988         case xr_int:
1989             if (value != NULL && octstr_parse_long(&lval, value, 0, 10) < 0) {
1990                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
1991                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse int value '%s'",
1992                                                    octstr_get_cstr(value));
1993                 octstr_destroy(value);
1994                 return -1;
1995             }
1996             xrvalue->v_type = xr_scalar;
1997             xrvalue->v_scalar = xmlrpc_scalar_create(xr_int, (void *) &lval);
1998             break;
1999 
2000         case xr_bool:
2001             if (value != NULL && octstr_parse_long(&lval, value, 0, 10) < 0) {
2002                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2003                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse boolean value '%s'",
2004                                                    octstr_get_cstr(value));
2005                 octstr_destroy(value);
2006                 return -1;
2007             }
2008             xrvalue->v_type = xr_scalar;
2009             xrvalue->v_scalar = xmlrpc_scalar_create(xr_bool, (void *) &lval);
2010             break;
2011 
2012         case xr_double:
2013             if (value != NULL && octstr_parse_double(&dval, value, 0) < 0) {
2014                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2015                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse double value '%s'",
2016                                                    octstr_get_cstr(value));
2017                 octstr_destroy(value);
2018                 return -1;
2019             }
2020             xrvalue->v_type = xr_scalar;
2021             xrvalue->v_scalar = xmlrpc_scalar_create(xr_double, (void *) &dval);
2022             break;
2023 
2024         case xr_string:
2025             xrvalue->v_type = xr_scalar;
2026             xrvalue->v_scalar = xmlrpc_scalar_create(xr_string, (void *) value);
2027             break;
2028 
2029         case xr_date:
2030             xrvalue->v_type = xr_scalar;
2031             xrvalue->v_scalar = xmlrpc_scalar_create(xr_date, (void *) value);
2032             break;
2033 
2034         case xr_base64:
2035             xrvalue->v_type = xr_scalar;
2036             xrvalue->v_scalar = xmlrpc_scalar_create(xr_base64, (void *) value);
2037             break;
2038 
2039         case xr_struct:
2040             xrvalue->v_type = xr_struct;
2041             xrvalue->v_struct = dict_create(OPTIMAL_STRUCT_SIZE, xmlrpc_value_destroy_item);
2042 
2043             if (parse_struct(doc, node->xmlChildrenNode, xrdoc, xrvalue->v_struct) == -1) {
2044                 octstr_destroy(value);
2045                 return -1;
2046             }
2047             break;
2048 
2049         case xr_array:
2050             xrvalue->v_type = xr_array;
2051             xrvalue->v_array = gwlist_create();
2052 
2053             if (parse_array(doc, node->xmlChildrenNode, xrdoc, xrvalue->v_array) == -1) {
2054                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2055                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse array");
2056                 octstr_destroy(value);
2057                 return -1;
2058             }
2059             break;
2060 
2061         default:
2062             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2063             xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_value!");
2064             return -1;
2065     }
2066 
2067     octstr_destroy(value);
2068     return 0;
2069 }
2070 
parse_struct(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,Dict * members)2071 static int parse_struct(xmlDocPtr doc, xmlNodePtr node,
2072                         XMLRPCDocument *xrdoc, Dict *members)
2073 {
2074     int status = 0;
2075 
2076     /* call for the parser function of the node type. */
2077     switch (node->type) {
2078 
2079         case XML_ELEMENT_NODE:
2080             status = parse_struct_element(doc, node, xrdoc, members);
2081             break;
2082 
2083         case XML_TEXT_NODE:
2084         case XML_COMMENT_NODE:
2085         case XML_PI_NODE:
2086             /* Text nodes, comments and PIs are ignored. */
2087             break;
2088            /*
2089             * XML has also many other node types, these are not needed with
2090             * XML-RPC. Therefore they are assumed to be an error.
2091             */
2092         default:
2093             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2094             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
2095             return -1;
2096             break;
2097     }
2098 
2099     if (node->next != NULL)
2100            if (parse_struct(doc, node->next, xrdoc, members) == -1)
2101             return -1;
2102 
2103     return status;
2104 }
2105 
parse_struct_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,Dict * members)2106 static int parse_struct_element(xmlDocPtr doc, xmlNodePtr node,
2107                                 XMLRPCDocument *xrdoc, Dict *members)
2108 {
2109     Octstr *name;
2110     size_t i;
2111     XMLRPCMember *member;
2112 
2113     /*
2114      * check if the element is allowed at this level
2115      */
2116     if (node->name == NULL) {
2117         error(0, "XMLRPC: XML struct element nodes without name!");
2118         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
2119         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
2120         return -1;
2121     }
2122 
2123     name = octstr_create(node->name);
2124     if (octstr_len(name) == 0) {
2125         octstr_destroy(name);
2126         return -1;
2127     }
2128 
2129     i = 0;
2130     while (i < NUMBER_OF_STRUCT_ELEMENTS) {
2131         if (octstr_case_compare(name, octstr_imm(struct_elements[i].name)) == 0)
2132             break;
2133         ++i;
2134     }
2135     if (i == NUMBER_OF_STRUCT_ELEMENTS) {
2136         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2137         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
2138                                            "in XML source at level <struct>",
2139                                            octstr_get_cstr(name));
2140         octstr_destroy(name);
2141         return -1;
2142     }
2143     octstr_destroy(name);
2144 
2145     /*
2146      * now check which type it is and process
2147      *
2148      * valid tags at this level are:
2149      *   member [0]
2150      */
2151     if (i == 0) {
2152         /* this has been a <member> tag */
2153         member = xmlrpc_member_create();
2154         if (parse_member(doc, node->xmlChildrenNode, xrdoc, member) == -1) {
2155             xmlrpc_member_destroy(member, 1);
2156             return -1;
2157         }
2158         if (! dict_put_once(members, member->name, member->value)) {
2159             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2160             xrdoc->parse_error = octstr_format("XML-RPC compiler: at least two members have same name.");
2161             xmlrpc_member_destroy(member, 1);
2162             return -1;
2163         }
2164         xmlrpc_member_destroy(member, 0);
2165     } else {
2166         /* we should never be here */
2167         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2168         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_struct!");
2169         return -1;
2170     }
2171     return 0;
2172 }
2173 
parse_member(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCMember * member)2174 static int parse_member(xmlDocPtr doc, xmlNodePtr node,
2175                         XMLRPCDocument *xrdoc, XMLRPCMember *member)
2176 {
2177     int status = 0;
2178 
2179     /* call for the parser function of the node type. */
2180     switch (node->type) {
2181 
2182         case XML_ELEMENT_NODE:
2183             status = parse_member_element(doc, node, xrdoc, member);
2184             break;
2185 
2186         case XML_TEXT_NODE:
2187         case XML_COMMENT_NODE:
2188         case XML_PI_NODE:
2189             /* Text nodes, comments and PIs are ignored. */
2190             break;
2191            /*
2192             * XML has also many other node types, these are not needed with
2193             * XML-RPC. Therefore they are assumed to be an error.
2194             */
2195         default:
2196             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2197             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
2198             return -1;
2199             break;
2200     }
2201 
2202     if (node->next != NULL)
2203            if (parse_member(doc, node->next, xrdoc, member) == -1)
2204             return -1;
2205 
2206     return status;
2207 }
2208 
parse_member_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCMember * member)2209 static int parse_member_element(xmlDocPtr doc, xmlNodePtr node,
2210                                 XMLRPCDocument *xrdoc, XMLRPCMember *member)
2211 {
2212     Octstr *name;
2213     xmlChar *content_buff;
2214     size_t i;
2215 
2216     /*
2217      * check if the element is allowed at this level
2218      */
2219     if (node->name == NULL) {
2220         error(0, "XMLRPC: XML member element nodes without name!");
2221         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
2222         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
2223         return -1;
2224     }
2225 
2226     name = octstr_create(node->name);
2227     if (octstr_len(name) == 0) {
2228         octstr_destroy(name);
2229         return -1;
2230     }
2231 
2232     i = 0;
2233     while (i < NUMBER_OF_MEMBER_ELEMENTS) {
2234         if (octstr_case_compare(name, octstr_imm(member_elements[i].name)) == 0)
2235             break;
2236         ++i;
2237     }
2238     if (i == NUMBER_OF_MEMBER_ELEMENTS) {
2239         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2240         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
2241                                            "in XML source at level <member>",
2242                                            octstr_get_cstr(name));
2243         octstr_destroy(name);
2244         return -1;
2245     }
2246     octstr_destroy(name);
2247 
2248     /*
2249      * now check which type it is and process
2250      *
2251      * valid tags at this level are:
2252      *   name [0]
2253      *   value [1]
2254      */
2255     if (i == 0) {
2256         /* this has been a <name> tag */
2257         if (member->name != NULL) {
2258             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2259             xrdoc->parse_error = octstr_format("XML-RPC compiler: duplicated tag '<name>' "
2260                                                "in XML source at level <member>");
2261             return -1;
2262         }
2263         content_buff = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
2264         if (content_buff != NULL) {
2265             member->name = octstr_create(content_buff);
2266             xmlFree(content_buff);
2267         } else {
2268             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2269             xrdoc->parse_error = octstr_format("XML-RPC compiler: empty tag <name> in XML source "
2270                                           "at level <member>");
2271             return -1;
2272         }
2273     } else {
2274         member->value = xmlrpc_value_create();
2275         if (parse_value(doc, node->xmlChildrenNode, xrdoc, member->value) == -1) {
2276             xmlrpc_value_destroy(member->value);
2277             member->value = NULL;
2278             return -1;
2279         }
2280     }
2281     return 0;
2282 }
2283 
parse_array(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * elements)2284 static int parse_array(xmlDocPtr doc, xmlNodePtr node,
2285                         XMLRPCDocument *xrdoc, List *elements)
2286 {
2287     int status = 0;
2288 
2289     /* call for the parser function of the node type. */
2290     switch (node->type) {
2291 
2292         case XML_ELEMENT_NODE:
2293             status = parse_array_element(doc, node, xrdoc, elements);
2294             break;
2295 
2296         case XML_TEXT_NODE:
2297         case XML_COMMENT_NODE:
2298         case XML_PI_NODE:
2299             /* Text nodes, comments and PIs are ignored. */
2300             break;
2301            /*
2302             * XML has also many other node types, these are not needed with
2303             * XML-RPC. Therefore they are assumed to be an error.
2304             */
2305         default:
2306             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2307             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
2308             return -1;
2309             break;
2310     }
2311 
2312     if (node->next != NULL)
2313            if (parse_array(doc, node->next, xrdoc, elements) == -1)
2314             return -1;
2315 
2316     return status;
2317 }
2318 
parse_array_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * elements)2319 static int parse_array_element(xmlDocPtr doc, xmlNodePtr node,
2320                                 XMLRPCDocument *xrdoc, List *elements)
2321 {
2322     Octstr *name;
2323     size_t i;
2324 
2325     /*
2326      * check if the element is allowed at this level
2327      */
2328     if (node->name == NULL) {
2329         error(0, "XMLRPC: XML array element nodes without name!");
2330         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
2331         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
2332         return -1;
2333     }
2334 
2335     name = octstr_create(node->name);
2336     if (octstr_len(name) == 0) {
2337         octstr_destroy(name);
2338         return -1;
2339     }
2340 
2341     i = 0;
2342     while (i < NUMBER_OF_ARRAY_ELEMENTS) {
2343         if (octstr_case_compare(name, octstr_imm(array_elements[i].name)) == 0)
2344             break;
2345         ++i;
2346     }
2347     if (i == NUMBER_OF_ARRAY_ELEMENTS) {
2348         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2349         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
2350                                            "in XML source at level <array>",
2351                                            octstr_get_cstr(name));
2352         octstr_destroy(name);
2353         return -1;
2354     }
2355     octstr_destroy(name);
2356 
2357     /*
2358      * now check which type it is and process
2359      *
2360      * valid tags at this level are:
2361      *   data [0]
2362      */
2363     if (i == 0) {
2364         /* this has been a <data> tag */
2365         if (parse_data(doc, node->xmlChildrenNode, xrdoc, elements) == -1)
2366             return -1;
2367 
2368     } else {
2369         /* we should never be here */
2370         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2371         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_array!");
2372         return -1;
2373     }
2374     return 0;
2375 }
2376 
parse_data(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * elements)2377 static int parse_data(xmlDocPtr doc, xmlNodePtr node,
2378                       XMLRPCDocument *xrdoc, List *elements)
2379 {
2380     int status = 0;
2381 
2382     /* call for the parser function of the node type. */
2383     switch (node->type) {
2384 
2385         case XML_ELEMENT_NODE:
2386             status = parse_data_element(doc, node, xrdoc, elements);
2387             break;
2388 
2389         case XML_TEXT_NODE:
2390         case XML_COMMENT_NODE:
2391         case XML_PI_NODE:
2392             /* Text nodes, comments and PIs are ignored. */
2393             break;
2394            /*
2395             * XML has also many other node types, these are not needed with
2396             * XML-RPC. Therefore they are assumed to be an error.
2397             */
2398         default:
2399             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2400             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
2401             return -1;
2402             break;
2403     }
2404 
2405     if (node->next != NULL)
2406            if (parse_data(doc, node->next, xrdoc, elements) == -1)
2407             return -1;
2408 
2409     return status;
2410 }
2411 
parse_data_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,List * elements)2412 static int parse_data_element(xmlDocPtr doc, xmlNodePtr node,
2413                               XMLRPCDocument *xrdoc, List *elements)
2414 {
2415     Octstr *name;
2416     XMLRPCValue *value;
2417     size_t i;
2418 
2419     /*
2420      * check if the element is allowed at this level
2421      */
2422     if (node->name == NULL) {
2423         error(0, "XMLRPC: XML data element nodes without name!");
2424         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
2425         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
2426         return -1;
2427     }
2428 
2429     name = octstr_create(node->name);
2430     if (octstr_len(name) == 0) {
2431         octstr_destroy(name);
2432         return -1;
2433     }
2434 
2435     i = 0;
2436     while (i < NUMBER_OF_DATA_ELEMENTS) {
2437         if (octstr_case_compare(name, octstr_imm(data_elements[i].name)) == 0)
2438             break;
2439         ++i;
2440     }
2441     if (i == NUMBER_OF_DATA_ELEMENTS) {
2442         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2443         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
2444                                            "in XML source at level <data>",
2445                                            octstr_get_cstr(name));
2446         octstr_destroy(name);
2447         return -1;
2448     }
2449     octstr_destroy(name);
2450 
2451     /*
2452      * now check which type it is and process
2453      *
2454      * valid tags at this level are:
2455      *  value [0]
2456      */
2457     if (i == 0) {
2458         /* this has been a <value> tag */
2459         value = xmlrpc_value_create();
2460         if (parse_value(doc, node->xmlChildrenNode, xrdoc, value) == -1) {
2461             xmlrpc_value_destroy(value);
2462             return -1;
2463         }
2464         gwlist_append(elements, value);
2465 
2466     } else {
2467         /* we should never be here */
2468         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2469         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_array!");
2470         return -1;
2471     }
2472     return 0;
2473 }
2474 
parse_fault(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCFault * fault)2475 static int parse_fault(xmlDocPtr doc, xmlNodePtr node,
2476                        XMLRPCDocument *xrdoc, XMLRPCFault *fault)
2477 {
2478     int status = 0;
2479 
2480     /* call for the parser function of the node type. */
2481     switch (node->type) {
2482 
2483         case XML_ELEMENT_NODE:
2484             status = parse_fault_element(doc, node, xrdoc, fault);
2485             break;
2486 
2487         case XML_TEXT_NODE:
2488         case XML_COMMENT_NODE:
2489         case XML_PI_NODE:
2490             /* Text nodes, comments and PIs are ignored. */
2491             break;
2492            /*
2493             * XML has also many other node types, these are not needed with
2494             * XML-RPC. Therefore they are assumed to be an error.
2495             */
2496         default:
2497             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2498             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
2499             return -1;
2500             break;
2501     }
2502 
2503     if (node->next != NULL)
2504            if (parse_fault(doc, node->next, xrdoc, fault) == -1)
2505             return -1;
2506 
2507     return status;
2508 }
2509 
parse_fault_element(xmlDocPtr doc,xmlNodePtr node,XMLRPCDocument * xrdoc,XMLRPCFault * fault)2510 static int parse_fault_element(xmlDocPtr doc, xmlNodePtr node,
2511                                XMLRPCDocument *xrdoc, XMLRPCFault *fault)
2512 {
2513     Octstr *name;
2514     XMLRPCValue *value, *v_code, *v_string;
2515     size_t i;
2516 
2517     /*
2518      * check if the element is allowed at this level
2519      */
2520     if (node->name == NULL) {
2521         error(0, "XMLRPC: XML fault element nodes without name!");
2522         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
2523         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
2524         return -1;
2525     }
2526 
2527     name = octstr_create(node->name);
2528     if (octstr_len(name) == 0) {
2529         octstr_destroy(name);
2530         return -1;
2531     }
2532 
2533     i = 0;
2534     while (i < NUMBER_OF_FAULT_ELEMENTS) {
2535         if (octstr_case_compare(name, octstr_imm(fault_elements[i].name)) == 0)
2536             break;
2537         ++i;
2538     }
2539     if (i == NUMBER_OF_FAULT_ELEMENTS) {
2540         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2541         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
2542                                            "in XML source at level <fault>",
2543                                            octstr_get_cstr(name));
2544         octstr_destroy(name);
2545         return -1;
2546     }
2547     octstr_destroy(name);
2548 
2549     /*
2550      * now check which type it is and process
2551      *
2552      * valid tags at this level are:
2553      *   value [0]
2554      */
2555     if (i == 0) {
2556         /* this has been a <value> tag */
2557         value = xmlrpc_value_create();
2558         if (parse_value(doc, node->xmlChildrenNode, xrdoc, value) == -1) {
2559             xmlrpc_value_destroy(value);
2560             return -1;
2561         }
2562         /* must be :
2563          *     <struct>
2564          *         <member>
2565          *             <name>faultCode</name>
2566          *             <value><int> ... </int></value>
2567          *         </member>
2568          *         <member>
2569          *             <name>faultString</name>
2570          *             <value><string> ... </string></value>
2571          *         </member>
2572          *     </struct>
2573          */
2574         if (xmlrpc_value_get_type(value) != xr_struct ||
2575             (v_code = xmlrpc_get_member(value, octstr_imm("faultCode"))) == NULL ||
2576             xmlrpc_value_get_type_smart(v_code) != xr_int ||
2577             (v_string = xmlrpc_get_member(value, octstr_imm("faultString"))) == NULL ||
2578             xmlrpc_value_get_type_smart(v_string) != xr_string ||
2579             xmlrpc_count_members(value) != 2) {
2580 
2581             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2582             xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus value "
2583                                                "in XML source at level <fault>");
2584             xmlrpc_value_destroy(value);
2585             return -1;
2586         }
2587 
2588         fault->f_code = xmlrpc_scalar_get_int((XMLRPCScalar *) xmlrpc_value_get_content(v_code));
2589         fault->f_string = xmlrpc_scalar_get_string((XMLRPCScalar *) xmlrpc_value_get_content(v_string));
2590 
2591         xmlrpc_value_destroy(value);
2592     } else {
2593         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
2594         xrdoc->parse_error = octstr_format("XML-RPC compiler: duplicated tag '<name>' "
2595                                            "in XML source at level <member>");
2596         return -1;
2597     }
2598     return 0;
2599 }
2600