initial load of upstream version 1.06.32
[xmlrpc-c] / src / xmlrpc_parse.c
1 /* Copyright information is at end of file. */
2
3 #include "xmlrpc_config.h"
4
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <ctype.h>
10
11 #include "bool.h"
12
13 #include "xmlrpc-c/base.h"
14 #include "xmlrpc-c/base_int.h"
15 #include "xmlrpc-c/string_int.h"
16 #include "xmlrpc-c/xmlparser.h"
17
18
19 /*=========================================================================
20 **  Data Format
21 **=========================================================================
22 **  An XML-RPC document consists of a single methodCall or methodResponse
23 **  element.
24 **
25 **  methodCall     methodName, params
26 **  methodResponse (params|fault)
27 **  params         param*
28 **  param          value
29 **  fault          value
30 **  value          (i4|int|boolean|string|double|dateTime.iso8601|base64|
31 **                  nil|struct|array)
32 **  array          data
33 **  data           value*
34 **  struct         member*
35 **  member         name, value
36 **
37 **  Contain CDATA: methodName, i4, int, boolean, string, double,
38 **                 dateTime.iso8601, base64, name
39 **
40 **  We attempt to validate the structure of the XML document carefully.
41 **  We also try *very* hard to handle malicious data gracefully, and without
42 **  leaking memory.
43 **
44 **  The CHECK_NAME and CHECK_CHILD_COUNT macros examine an XML element, and
45 **  invoke XMLRPC_FAIL if something looks wrong.
46 */
47
48 #define CHECK_NAME(env,elem,name) \
49     do \
50         if (!xmlrpc_streq((name), xml_element_name(elem))) \
51             XMLRPC_FAIL2(env, XMLRPC_PARSE_ERROR, \
52              "Expected element of type <%s>, found <%s>", \
53                          (name), xml_element_name(elem)); \
54     while (0)
55
56 #define CHECK_CHILD_COUNT(env,elem,count) \
57     do \
58         if (xml_element_children_size(elem) != (count)) \
59             XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR, \
60              "Expected <%s> to have %d children, found %d", \
61                          xml_element_name(elem), (count), \
62                          xml_element_children_size(elem)); \
63     while (0)
64
65 static xml_element *
66 get_child_by_name (xmlrpc_env *env, xml_element *parent, char *name)
67 {
68     size_t child_count, i;
69     xml_element **children;
70
71     children = xml_element_children(parent);
72     child_count = xml_element_children_size(parent);
73     for (i = 0; i < child_count; i++) {
74         if (xmlrpc_streq(xml_element_name(children[i]), name))
75             return children[i];
76     }
77     
78     xmlrpc_env_set_fault_formatted(env, XMLRPC_PARSE_ERROR,
79                                    "Expected <%s> to have child <%s>",
80                                    xml_element_name(parent), name);
81     return NULL;
82 }
83
84
85 /*=========================================================================
86 **  Number-Parsing Functions
87 **=========================================================================
88 **  These functions mirror atoi, atof, etc., but provide better
89 **  error-handling.  These routines may reset errno to zero.
90 */
91
92 static xmlrpc_int32
93 xmlrpc_atoi(xmlrpc_env *env, char *str, size_t strlen,
94             xmlrpc_int32 min, xmlrpc_int32 max)
95 {
96     long i;
97     char *end;
98
99     XMLRPC_ASSERT_ENV_OK(env);
100     XMLRPC_ASSERT_PTR_OK(str);
101
102     /* Suppress compiler warnings. */
103     i = 0;
104
105     /* Check for leading white space. */
106     if (isspace(str[0]))
107     XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
108                  "\"%s\" must not contain whitespace", str);
109
110     /* Convert the value. */
111     end = str + strlen;
112     errno = 0;
113     i = strtol(str, &end, 10);
114
115     /* Look for ERANGE. */
116     if (errno != 0)
117         /* XXX - Do all operating systems have thread-safe strerror? */
118         XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
119                      "error parsing \"%s\": %s (%d)",
120                      str, strerror(errno), errno);
121     
122     /* Look for out-of-range errors which didn't produce ERANGE. */
123     if (i < min || i > max)
124         XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
125                      "\"%s\" must be in range %d to %d", str, min, max);
126
127     /* Check for unused characters. */
128     if (end != str + strlen)
129         XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
130                      "\"%s\" contained trailing data", str);
131     
132  cleanup:
133     errno = 0;
134     if (env->fault_occurred)
135         return 0;
136     return (xmlrpc_int32) i;
137 }
138
139
140
141 static double
142 xmlrpc_atod(xmlrpc_env *env, char *str, size_t strlen)
143 {
144     double d;
145     char *end;
146
147     XMLRPC_ASSERT_ENV_OK(env);
148     XMLRPC_ASSERT_PTR_OK(str);
149
150     /* Suppress compiler warnings. */
151     d = 0.0;
152
153     /* Check for leading white space. */
154     if (isspace(str[0]))
155         XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
156                      "\"%s\" must not contain whitespace", str);
157     
158     /* Convert the value. */
159     end = str + strlen;
160     errno = 0;
161     d = strtod(str, &end);
162     
163     /* Look for ERANGE. */
164     if (errno != 0)
165         /* XXX - Do all operating systems have thread-safe strerror? */
166         XMLRPC_FAIL3(env, XMLRPC_PARSE_ERROR,
167                      "error parsing \"%s\": %s (%d)",
168                      str, strerror(errno), errno);
169     
170     /* Check for unused characters. */
171     if (end != str + strlen)
172         XMLRPC_FAIL1(env, XMLRPC_PARSE_ERROR,
173                      "\"%s\" contained trailing data", str);
174
175  cleanup:
176     errno = 0;
177     if (env->fault_occurred)
178         return 0.0;
179     return d;
180 }
181
182
183 /*=========================================================================
184 **  make_string
185 **=========================================================================
186 **  Make an XML-RPC string.
187 **
188 ** SECURITY: We validate our UTF-8 first.  This incurs a performance
189 ** penalty, but ensures that we will never pass maliciously malformed
190 ** UTF-8 data back up to the user layer, where it could wreak untold
191 ** damange. Don't comment out this check unless you know *exactly* what
192 ** you're doing.  (Win32 developers who remove this check are *begging*
193 ** to wind up on BugTraq, because many of the Win32 filesystem routines
194 ** rely on an insecure UTF-8 decoder.)
195 **
196 ** XXX - This validation is redundant if the user chooses to convert
197 ** UTF-8 data into a wchar_t string.
198 */
199
200 static xmlrpc_value *
201 make_string(xmlrpc_env * const envP,
202             char *       const cdata,
203             size_t       const cdata_size) {
204 #if HAVE_UNICODE_WCHAR
205     xmlrpc_validate_utf8(envP, cdata, cdata_size);
206 #endif
207
208     if (envP->fault_occurred)
209         return NULL;
210     return xmlrpc_build_value(envP, "s#", cdata, cdata_size);
211 }
212
213
214
215 /* Forward declaration for recursion */
216 static xmlrpc_value *
217 convert_value(xmlrpc_env *  const envP,
218               unsigned int  const maxRecursion,
219               xml_element * const elemP);
220
221
222
223 static void
224 convertBase64(xmlrpc_env *    const envP,
225               const char *    const cdata,
226               size_t          const cdata_size,
227               xmlrpc_value ** const valuePP) {
228     
229     xmlrpc_mem_block *decoded;
230     
231     decoded = xmlrpc_base64_decode(envP, cdata, cdata_size);
232     if (!envP->fault_occurred) {
233         unsigned char * const asciiData =
234             XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded);
235         size_t const asciiLen =
236             XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded);
237
238         *valuePP = xmlrpc_build_value(envP, "6", asciiData, asciiLen);
239         
240         XMLRPC_MEMBLOCK_FREE(unsigned char, decoded);
241     }
242 }
243
244
245
246 /*=========================================================================
247 **  convert_array
248 **=========================================================================
249 **  Convert an XML element representing an array into an xmlrpc_value.
250 */
251
252 static xmlrpc_value *
253 convert_array(xmlrpc_env *  const envP,
254               unsigned int  const maxRecursion,
255               xml_element * const elemP) {
256
257     xml_element *data, **values, *value;
258     xmlrpc_value *array, *item;
259     int size, i;
260
261     XMLRPC_ASSERT_ENV_OK(envP);
262     XMLRPC_ASSERT(elemP != NULL);
263
264     /* Set up our error-handling preconditions. */
265     array = item = NULL;
266
267     /* Allocate an array to hold our values. */
268     array = xmlrpc_build_value(envP, "()");
269     XMLRPC_FAIL_IF_FAULT(envP);
270
271     /* We don't need to check our element name--our callers do that. */
272     CHECK_CHILD_COUNT(envP, elemP, 1);
273     data = xml_element_children(elemP)[0];
274     CHECK_NAME(envP, data, "data");
275     
276     /* Iterate over our children. */
277     values = xml_element_children(data);
278     size = xml_element_children_size(data);
279     for (i = 0; i < size; i++) {
280         value = values[i];
281         item = convert_value(envP, maxRecursion-1, value);
282         XMLRPC_FAIL_IF_FAULT(envP);
283
284         xmlrpc_array_append_item(envP, array, item);
285         xmlrpc_DECREF(item);
286         item = NULL;
287         XMLRPC_FAIL_IF_FAULT(envP);
288     }
289
290  cleanup:
291     if (item)
292         xmlrpc_DECREF(item);
293     if (envP->fault_occurred) {
294         if (array)
295             xmlrpc_DECREF(array);
296         return NULL;
297     }
298     return array;
299 }
300
301
302
303 /*=========================================================================
304 **  convert_struct
305 **=========================================================================
306 **  Convert an XML element representing a struct into an xmlrpc_value.
307 */
308
309 static xmlrpc_value *
310 convert_struct(xmlrpc_env *  const envP,
311                unsigned int  const maxRecursion,
312                xml_element * const elemP) {
313
314     xmlrpc_value *strct, *key, *value;
315     xml_element **members, *member, *name_elemP, *value_elemP;
316     int size, i;
317     char *cdata;
318     size_t cdata_size;
319
320     XMLRPC_ASSERT_ENV_OK(envP);
321     XMLRPC_ASSERT(elemP != NULL);
322
323     /* Set up our error-handling preconditions. */
324     strct = key = value = NULL;
325
326     /* Allocate an array to hold our members. */
327     strct = xmlrpc_struct_new(envP);
328     XMLRPC_FAIL_IF_FAULT(envP);
329
330     /* Iterate over our children, extracting key/value pairs. */
331     /* We don't need to check our element name--our callers do that. */
332     members = xml_element_children(elemP);
333     size = xml_element_children_size(elemP);
334     for (i = 0; i < size; i++) {
335         member = members[i];
336         CHECK_NAME(envP, member, "member");
337         CHECK_CHILD_COUNT(envP, member, 2);
338
339         /* Get our key. */
340         name_elemP = get_child_by_name(envP, member, "name");
341         XMLRPC_FAIL_IF_FAULT(envP);
342         CHECK_CHILD_COUNT(envP, name_elemP, 0);
343         cdata = xml_element_cdata(name_elemP);
344         cdata_size = xml_element_cdata_size(name_elemP);
345         key = make_string(envP, cdata, cdata_size);
346         XMLRPC_FAIL_IF_FAULT(envP);
347
348         /* Get our value. */
349         value_elemP = get_child_by_name(envP, member, "value");
350         XMLRPC_FAIL_IF_FAULT(envP);
351         value = convert_value(envP, maxRecursion-1, value_elemP);
352         XMLRPC_FAIL_IF_FAULT(envP);
353
354         /* Add the key/value pair to our struct. */
355         xmlrpc_struct_set_value_v(envP, strct, key, value);
356         XMLRPC_FAIL_IF_FAULT(envP);
357
358         /* Release our references & memory, and restore our invariants. */
359         xmlrpc_DECREF(key);
360         key = NULL;
361         xmlrpc_DECREF(value);
362         value = NULL;
363     }
364     
365  cleanup:
366     if (key)
367         xmlrpc_DECREF(key);
368     if (value)
369         xmlrpc_DECREF(value);
370     if (envP->fault_occurred) {
371         if (strct)
372             xmlrpc_DECREF(strct);
373         return NULL;
374     }
375     return strct;
376 }
377
378
379
380 static xmlrpc_value *
381 convert_value(xmlrpc_env *  const envP,
382               unsigned int  const maxRecursion,
383               xml_element * const elemP) {
384 /*----------------------------------------------------------------------------
385    Compute the xmlrpc_value represented by the XML <value> element 'elem'.
386    Return that xmlrpc_value.
387
388    We call convert_array() and convert_struct(), which may ultimately
389    call us recursively.  Don't recurse any more than 'maxRecursion'
390    times.
391 -----------------------------------------------------------------------------*/
392     int child_count;
393     xmlrpc_value * retval;
394
395     XMLRPC_ASSERT_ENV_OK(envP);
396     XMLRPC_ASSERT(elemP != NULL);
397
398     /* Error-handling preconditions.
399     ** If we haven't changed any of these from their default state, we're
400     ** allowed to tail-call xmlrpc_build_value. */
401     retval = NULL;
402
403     /* Assume we'll need to recurse, make sure we're allowed */
404     if (maxRecursion < 1) 
405         XMLRPC_FAIL(envP, XMLRPC_PARSE_ERROR,
406                     "Nested data structure too deep.");
407
408     /* Validate our structure, and see whether we have a child element. */
409     CHECK_NAME(envP, elemP, "value");
410     child_count = xml_element_children_size(elemP);
411
412     if (child_count == 0) {
413         /* We have no type element, so treat the value as a string. */
414         char * const cdata      = xml_element_cdata(elemP);
415         size_t const cdata_size = xml_element_cdata_size(elemP);
416         retval = make_string(envP, cdata, cdata_size);
417     } else {
418         /* We should have a type tag inside our value tag. */
419         xml_element * child;
420         const char * child_name;
421         
422         CHECK_CHILD_COUNT(envP, elemP, 1);
423         child = xml_element_children(elemP)[0];
424         
425         /* Parse our value-containing element. */
426         child_name = xml_element_name(child);
427         if (xmlrpc_streq(child_name, "struct")) {
428             retval = convert_struct(envP, maxRecursion, child);
429         } else if (xmlrpc_streq(child_name, "array")) {
430             CHECK_CHILD_COUNT(envP, child, 1);
431             retval = convert_array(envP, maxRecursion, child);
432         } else {
433             char * cdata;
434             size_t cdata_size;
435
436             CHECK_CHILD_COUNT(envP, child, 0);
437             cdata = xml_element_cdata(child);
438             cdata_size = xml_element_cdata_size(child);
439             if (xmlrpc_streq(child_name, "i4") ||
440                 xmlrpc_streq(child_name, "int")) {
441                 xmlrpc_int32 const i =
442                     xmlrpc_atoi(envP, cdata, strlen(cdata),
443                                 XMLRPC_INT32_MIN, XMLRPC_INT32_MAX);
444                 XMLRPC_FAIL_IF_FAULT(envP);
445                 retval = xmlrpc_build_value(envP, "i", i);
446             } else if (xmlrpc_streq(child_name, "string")) {
447                 retval = make_string(envP, cdata, cdata_size);
448             } else if (xmlrpc_streq(child_name, "boolean")) {
449                 xmlrpc_int32 const i =
450                     xmlrpc_atoi(envP, cdata, strlen(cdata), 0, 1);
451                 XMLRPC_FAIL_IF_FAULT(envP);
452                 retval = xmlrpc_build_value(envP, "b", (xmlrpc_bool) i);
453             } else if (xmlrpc_streq(child_name, "double")) {
454                 double const d = xmlrpc_atod(envP, cdata, strlen(cdata));
455                 XMLRPC_FAIL_IF_FAULT(envP);
456                 retval = xmlrpc_build_value(envP, "d", d);
457             } else if (xmlrpc_streq(child_name, "dateTime.iso8601")) {
458                 retval = xmlrpc_build_value(envP, "8", cdata);
459             } else if (xmlrpc_streq(child_name, "nil")) {
460                 retval = xmlrpc_build_value(envP, "n");
461             } else if (xmlrpc_streq(child_name, "base64")) {
462                 /* No more tail calls once we do this! */
463
464                 convertBase64(envP, cdata, cdata_size, &retval);
465                 if (envP->fault_occurred)
466                     /* Just for cleanup code: */
467                     retval = NULL;
468             } else {
469                 XMLRPC_FAIL1(envP, XMLRPC_PARSE_ERROR,
470                              "Unknown value type -- XML element is named "
471                              "<%s>", child_name);
472             }
473         }
474     }
475
476  cleanup:
477     if (envP->fault_occurred) {
478         if (retval)
479             xmlrpc_DECREF(retval);
480         retval = NULL;
481     }
482     return retval;
483 }
484
485
486
487 /*=========================================================================
488 **  convert_params
489 **=========================================================================
490 **  Convert an XML element representing a list of params into an
491 **  xmlrpc_value (of type array).
492 */
493
494 static xmlrpc_value *
495 convert_params(xmlrpc_env *        const envP,
496                const xml_element * const elemP) {
497 /*----------------------------------------------------------------------------
498    Convert an XML element representing a list of parameters (i.e.  a
499    <params> element) to an xmlrpc_value of type array.  Note that an
500    array is normally represented in XML by a <value> element.  We use
501    type xmlrpc_value to represent the parameter list just for convenience.
502 -----------------------------------------------------------------------------*/
503     xmlrpc_value *array, *item;
504     int size, i;
505     xml_element **params, *param, *value;
506
507     XMLRPC_ASSERT_ENV_OK(envP);
508     XMLRPC_ASSERT(elemP != NULL);
509
510     /* Set up our error-handling preconditions. */
511     array = item = NULL;
512
513     /* Allocate an array to hold our parameters. */
514     array = xmlrpc_build_value(envP, "()");
515     XMLRPC_FAIL_IF_FAULT(envP);
516
517     /* We're responsible for checking our own element name. */
518     CHECK_NAME(envP, elemP, "params");    
519
520     /* Iterate over our children. */
521     size = xml_element_children_size(elemP);
522     params = xml_element_children(elemP);
523     for (i = 0; i < size; ++i) {
524         unsigned int const maxNest = xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);
525
526         param = params[i];
527         CHECK_NAME(envP, param, "param");
528         CHECK_CHILD_COUNT(envP, param, 1);
529
530         value = xml_element_children(param)[0];
531         item = convert_value(envP, maxNest, value);
532         XMLRPC_FAIL_IF_FAULT(envP);
533
534         xmlrpc_array_append_item(envP, array, item);
535         xmlrpc_DECREF(item);
536         item = NULL;
537         XMLRPC_FAIL_IF_FAULT(envP);
538     }
539
540  cleanup:
541     if (envP->fault_occurred) {
542         if (array)
543             xmlrpc_DECREF(array);
544         if (item)
545             xmlrpc_DECREF(item);
546         return NULL;
547     }
548     return array;
549 }
550
551
552
553 static void
554 parseCallXml(xmlrpc_env *   const envP,
555              const char *   const xmlData,
556              size_t         const xmlLen,
557              xml_element ** const callElemPP) {
558
559     xml_element * callElemP;
560     xmlrpc_env env;
561
562     xmlrpc_env_init(&env);
563     xml_parse(&env, xmlData, xmlLen, &callElemP);
564     if (env.fault_occurred)
565         xmlrpc_env_set_fault_formatted(
566             envP, env.fault_code, "Call is not valid XML.  %s",
567             env.fault_string);
568     else {
569         if (!xmlrpc_streq(xml_element_name(callElemP), "methodCall"))
570             xmlrpc_env_set_fault_formatted(
571                 envP, XMLRPC_PARSE_ERROR,
572                 "XML-RPC call should be a <methodCall> element.  "
573                 "Instead, we have a <%s> element.",
574                 xml_element_name(callElemP));
575
576         if (!envP->fault_occurred)
577             *callElemPP = callElemP;
578
579         if (envP->fault_occurred)
580             xml_element_free(callElemP);
581     }
582     xmlrpc_env_clean(&env);
583 }
584
585
586
587 static void
588 parseMethodNameElement(xmlrpc_env *  const envP,
589                        xml_element * const nameElemP,
590                        const char ** const methodNameP) {
591     
592     XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(nameElemP), "methodName"));
593
594     if (xml_element_children_size(nameElemP) > 0)
595         xmlrpc_env_set_fault_formatted(
596             envP, XMLRPC_PARSE_ERROR,
597             "A <methodName> element should not have children.  "
598             "This one has %u of them.", xml_element_children_size(nameElemP));
599     else {
600         const char * const cdata = xml_element_cdata(nameElemP);
601
602         xmlrpc_validate_utf8(envP, cdata, strlen(cdata));
603
604         if (!envP->fault_occurred) {
605             *methodNameP = strdup(cdata);
606             if (*methodNameP == NULL)
607                 xmlrpc_faultf(envP,
608                               "Could not allocate memory for method name");
609         }
610     }
611 }            
612
613
614
615 static void
616 parseCallChildren(xmlrpc_env *    const envP,
617                   xml_element *   const callElemP,
618                   const char **   const methodNameP,
619                   xmlrpc_value ** const paramArrayPP ) {
620 /*----------------------------------------------------------------------------
621   Parse the children of a <methodCall> XML element *callElemP.  They should
622   be <methodName> and <params>.
623 -----------------------------------------------------------------------------*/
624     size_t const callChildCount = xml_element_children_size(callElemP);
625
626     xml_element * nameElemP;
627         
628     XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(callElemP), "methodCall"));
629     
630     nameElemP = get_child_by_name(envP, callElemP, "methodName");
631     
632     if (!envP->fault_occurred) {
633         parseMethodNameElement(envP, nameElemP, methodNameP);
634             
635         if (!envP->fault_occurred) {
636             /* Convert our parameters. */
637             if (callChildCount > 1) {
638                 xml_element * paramsElemP;
639
640                 paramsElemP = get_child_by_name(envP, callElemP, "params");
641                     
642                 if (!envP->fault_occurred)
643                     *paramArrayPP = convert_params(envP, paramsElemP);
644             } else {
645                 /* Workaround for Ruby XML-RPC and old versions of
646                    xmlrpc-epi.  Future improvement: Instead of looking
647                    at child count, we should just check for existence
648                    of <params>.
649                 */
650                 *paramArrayPP = xmlrpc_array_new(envP);
651             }
652             if (!envP->fault_occurred) {
653                 if (callChildCount > 2)
654                     xmlrpc_env_set_fault_formatted(
655                         envP, XMLRPC_PARSE_ERROR,
656                         "<methodCall> has extraneous children, other than "
657                         "<methodName> and <params>.  Total child count = %u",
658                         callChildCount);
659                     
660                 if (envP->fault_occurred)
661                     xmlrpc_DECREF(*paramArrayPP);
662             }
663             if (envP->fault_occurred)
664                 xmlrpc_strfree(*methodNameP);
665         }
666     }
667 }
668
669
670
671 /*=========================================================================
672 **  xmlrpc_parse_call
673 **=========================================================================
674 **  Given some XML text, attempt to parse it as an XML-RPC call. Return
675 **  a newly allocated xmlrpc_call structure (or NULL, if an error occurs).
676 **  The two output variables will contain either valid values (which
677 **  must free() and xmlrpc_DECREF(), respectively) or NULLs (if an error
678 **  occurs).
679 */
680
681 void 
682 xmlrpc_parse_call(xmlrpc_env *    const envP,
683                   const char *    const xmlData,
684                   size_t          const xmlLen,
685                   const char **   const methodNameP,
686                   xmlrpc_value ** const paramArrayPP) {
687
688     XMLRPC_ASSERT_ENV_OK(envP);
689     XMLRPC_ASSERT(xmlData != NULL);
690     XMLRPC_ASSERT(methodNameP != NULL && paramArrayPP != NULL);
691
692     /* SECURITY: Last-ditch attempt to make sure our content length is
693        legal.  XXX - This check occurs too late to prevent an attacker
694        from creating an enormous memory block, so you should try to
695        enforce it *before* reading any data off the network.
696      */
697     if (xmlLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
698         xmlrpc_env_set_fault_formatted(
699             envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
700             "XML-RPC request too large.  Max allowed is %u bytes",
701             xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID));
702     else {
703         xml_element * callElemP;
704         parseCallXml(envP, xmlData, xmlLen, &callElemP);
705         if (!envP->fault_occurred) {
706             parseCallChildren(envP, callElemP, methodNameP, paramArrayPP);
707
708             xml_element_free(callElemP);
709         }
710     }
711     if (envP->fault_occurred) {
712         *methodNameP  = NULL;
713         *paramArrayPP = NULL;
714     }
715 }
716
717
718
719 static void
720 interpretFaultValue(xmlrpc_env *   const envP,
721                     xmlrpc_value * const faultVP,
722                     int *          const faultCodeP,
723                     const char **  const faultStringP) {
724                 
725     if (faultVP->_type != XMLRPC_TYPE_STRUCT)
726         xmlrpc_env_set_fault(
727             envP, XMLRPC_PARSE_ERROR,
728             "<value> element of <fault> response contains is not "
729             "of structure type");
730     else {
731         xmlrpc_value * faultCodeVP;
732         xmlrpc_env fvEnv;
733
734         xmlrpc_env_init(&fvEnv);
735
736         xmlrpc_struct_read_value(&fvEnv, faultVP, "faultCode", &faultCodeVP);
737         if (!fvEnv.fault_occurred) {
738             xmlrpc_read_int(&fvEnv, faultCodeVP, faultCodeP);
739             if (!fvEnv.fault_occurred) {
740                 xmlrpc_value * faultStringVP;
741
742                 xmlrpc_struct_read_value(&fvEnv, faultVP, "faultString",
743                                          &faultStringVP);
744                 if (!fvEnv.fault_occurred) {
745                     xmlrpc_read_string(&fvEnv, faultStringVP, faultStringP);
746                     xmlrpc_DECREF(faultStringVP);
747                 }
748             }
749             xmlrpc_DECREF(faultCodeVP);
750         }
751         if (fvEnv.fault_occurred)
752             xmlrpc_env_set_fault_formatted(
753                 envP, XMLRPC_PARSE_ERROR,
754                 "Invalid struct for <fault> value.  %s", fvEnv.fault_string);
755
756         xmlrpc_env_clean(&fvEnv);
757     }
758 }
759
760
761
762 static void
763 parseFaultElement(xmlrpc_env *        const envP,
764                   const xml_element * const faultElement,
765                   int *               const faultCodeP,
766                   const char **       const faultStringP) {
767                   
768     unsigned int const maxRecursion =
769         xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID);
770
771     XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(faultElement), "fault"));
772
773     if (xml_element_children_size(faultElement) != 1)
774         xmlrpc_env_set_fault_formatted(
775             envP, XMLRPC_PARSE_ERROR,
776             "<fault> element should have 1 child, but it has %u.",
777             xml_element_children_size(faultElement));
778     else {
779         xml_element * const faultValueP =
780             xml_element_children(faultElement)[0];
781
782         xmlrpc_value * faultVP;
783
784         faultVP = convert_value(envP, maxRecursion, faultValueP);
785         
786         if (!envP->fault_occurred) {
787             interpretFaultValue(envP, faultVP, faultCodeP, faultStringP);
788
789             xmlrpc_DECREF(faultVP);
790         }
791     }
792 }
793
794
795
796 static void
797 parseParamsElement(xmlrpc_env *        const envP,
798                    const xml_element * const paramsElementP,
799                    xmlrpc_value **     const resultPP) {
800
801     xmlrpc_value * paramsVP;
802     xmlrpc_env env;
803
804     xmlrpc_env_init(&env);
805
806     XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(paramsElementP), "params"));
807
808     paramsVP = convert_params(envP, paramsElementP);
809
810     if (!envP->fault_occurred) {
811         int arraySize;
812         xmlrpc_env sizeEnv;
813
814         XMLRPC_ASSERT_ARRAY_OK(paramsVP);
815         
816         xmlrpc_env_init(&sizeEnv);
817
818         arraySize = xmlrpc_array_size(&sizeEnv, paramsVP);
819         /* Since it's a valid array, as asserted above, can't fail */
820         XMLRPC_ASSERT(!sizeEnv.fault_occurred);
821
822         if (arraySize != 1)
823             xmlrpc_env_set_fault_formatted(
824                 &env, XMLRPC_PARSE_ERROR,
825                 "Contains %d items.  It should have 1.",
826                 arraySize);
827         else {
828             xmlrpc_array_read_item(envP, paramsVP, 0, resultPP);
829         }
830         xmlrpc_DECREF(paramsVP);
831         xmlrpc_env_clean(&sizeEnv);
832     }
833     if (env.fault_occurred)
834         xmlrpc_env_set_fault_formatted(
835             envP, env.fault_code,
836             "Invalid <params> element.  %s", env.fault_string);
837
838     xmlrpc_env_clean(&env);
839 }
840
841
842
843 static void
844 parseMethodResponseElt(xmlrpc_env *        const envP,
845                        const xml_element * const methodResponseEltP,
846                        xmlrpc_value **     const resultPP,
847                        int *               const faultCodeP,
848                        const char **       const faultStringP) {
849     
850     XMLRPC_ASSERT(xmlrpc_streq(xml_element_name(methodResponseEltP),
851                                "methodResponse"));
852
853     if (xml_element_children_size(methodResponseEltP) == 1) {
854         xml_element * const child =
855             xml_element_children(methodResponseEltP)[0];
856         
857         if (xmlrpc_streq(xml_element_name(child), "params")) {
858             /* It's a successful response */
859             parseParamsElement(envP, child, resultPP);
860             *faultStringP = NULL;
861         } else if (xmlrpc_streq(xml_element_name(child), "fault")) {
862             /* It's a failure response */
863             parseFaultElement(envP, child, faultCodeP, faultStringP);
864         } else
865             xmlrpc_env_set_fault_formatted(
866                 envP, XMLRPC_PARSE_ERROR,
867                 "<methodResponse> must contain <params> or <fault>, "
868                 "but contains <%s>.", xml_element_name(child));
869     } else
870         xmlrpc_env_set_fault_formatted(
871             envP, XMLRPC_PARSE_ERROR,
872             "<methodResponse> has %u children, should have 1.",
873             xml_element_children_size(methodResponseEltP));
874 }
875
876
877
878 void
879 xmlrpc_parse_response2(xmlrpc_env *    const envP,
880                        const char *    const xmlData,
881                        size_t          const xmlDataLen,
882                        xmlrpc_value ** const resultPP,
883                        int *           const faultCodeP,
884                        const char **   const faultStringP) {
885 /*----------------------------------------------------------------------------
886   Given some XML text, attempt to parse it as an XML-RPC response.
887
888   If the response is a regular, valid response, return a new reference
889   to the appropriate value as *resultP and return NULL as
890   *faultStringP and nothing as *faultCodeP.
891
892   If the response valid, but indicates a failure of the RPC, return the
893   fault string in newly malloc'ed space as *faultStringP and the fault
894   code as *faultCodeP and nothing as *resultP.
895
896   If the XML text is not a valid response or something prevents us from
897   parsing it, return a description of the error as *envP and nothing else.
898 -----------------------------------------------------------------------------*/
899     xml_element * response;
900
901     XMLRPC_ASSERT_ENV_OK(envP);
902     XMLRPC_ASSERT(xmlData != NULL);
903
904     /* SECURITY: Last-ditch attempt to make sure our content length is legal.
905     ** XXX - This check occurs too late to prevent an attacker from creating
906     ** an enormous memory block, so you should try to enforce it
907     ** *before* reading any data off the network. */
908     if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
909         xmlrpc_env_set_fault_formatted(
910             envP, XMLRPC_LIMIT_EXCEEDED_ERROR,
911             "XML-RPC response too large.  Our limit is %u characters.  "
912             "We got %u characters",
913             xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID), xmlDataLen);
914     else {
915         xml_parse(envP, xmlData, xmlDataLen, &response);
916         if (!envP->fault_occurred) {
917             /* Pick apart and verify our structure. */
918             if (xmlrpc_streq(xml_element_name(response), "methodResponse")) {
919                 parseMethodResponseElt(envP, response,
920                                        resultPP, faultCodeP, faultStringP);
921             } else
922                 xmlrpc_env_set_fault_formatted(
923                     envP, XMLRPC_PARSE_ERROR,
924                     "XML-RPC response must consist of a "
925                     "<methodResponse> element.  This has a <%s> instead.",
926                     xml_element_name(response));
927             
928             xml_element_free(response);
929         }
930     }
931 }
932
933
934
935 xmlrpc_value *
936 xmlrpc_parse_response(xmlrpc_env * const envP,
937                       const char * const xmlData,
938                       size_t       const xmlDataLen) {
939 /*----------------------------------------------------------------------------
940    This exists for backward compatibility.  It is like
941    xmlrpc_parse_response2(), except that it merges the concepts of a
942    failed RPC and an error in executing the RPC.
943 -----------------------------------------------------------------------------*/
944     xmlrpc_value * retval;
945     xmlrpc_value * result;
946     const char * faultString;
947     int faultCode;
948
949     xmlrpc_parse_response2(envP, xmlData, xmlDataLen,
950                            &result, &faultCode, &faultString);
951     
952     if (envP->fault_occurred)
953         retval = NULL;
954     else {
955         if (faultString) {
956             xmlrpc_env_set_fault(envP, faultCode, faultString);
957             xmlrpc_strfree(faultString);
958             retval = NULL;
959         } else
960             retval = result;  /* transfer reference */
961     }
962     return retval;
963 }
964
965
966
967 /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
968 **
969 ** Redistribution and use in source and binary forms, with or without
970 ** modification, are permitted provided that the following conditions
971 ** are met:
972 ** 1. Redistributions of source code must retain the above copyright
973 **    notice, this list of conditions and the following disclaimer.
974 ** 2. Redistributions in binary form must reproduce the above copyright
975 **    notice, this list of conditions and the following disclaimer in the
976 **    documentation and/or other materials provided with the distribution.
977 ** 3. The name of the author may not be used to endorse or promote products
978 **    derived from this software without specific prior written permission. 
979 **  
980 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
981 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
982 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
983 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
984 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
985 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
986 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
987 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
988 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
989 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
990 ** SUCH DAMAGE. */