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