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