1 /* Copyright information is at end of file */
3 #include "xmlrpc_config.h"
12 #include "xmlrpc_int.h"
14 /* Borrowed from Python 1.5.2.
15 ** MPW pushes 'extended' for float and double types with varargs */
17 typedef extended va_double
;
19 typedef double va_double
;
22 /* Borrowed from Python 1.5.2.
23 ** Python copies its va_list objects before using them in certain
24 ** tricky fashions. We don't why Python does this, but since we're
25 ** abusing our va_list objects in a similar fashion, we'll copy them
28 # define VA_LIST_COPY(dest,src) va_copy((dest), (src))
31 # define VA_LIST_COPY(dest,src) memcpy((dest), (src), sizeof(va_list))
33 # define VA_LIST_COPY(dest,src) ((dest) = (src))
39 destroyValue(xmlrpc_value
* const valueP
) {
41 /* First, we need to destroy this value's contents, if any. */
42 switch (valueP
->_type
) {
44 case XMLRPC_TYPE_BOOL
:
45 case XMLRPC_TYPE_DOUBLE
:
48 case XMLRPC_TYPE_ARRAY
:
49 xmlrpc_destroyArrayContents(valueP
);
52 case XMLRPC_TYPE_STRING
:
53 #ifdef HAVE_UNICODE_WCHAR
54 if (valueP
->_wcs_block
)
55 xmlrpc_mem_block_free(valueP
->_wcs_block
);
56 #endif /* HAVE_UNICODE_WCHAR */
59 case XMLRPC_TYPE_DATETIME
:
60 case XMLRPC_TYPE_BASE64
:
61 xmlrpc_mem_block_clean(&valueP
->_block
);
64 case XMLRPC_TYPE_STRUCT
:
65 xmlrpc_destroyStruct(valueP
);
68 case XMLRPC_TYPE_C_PTR
:
71 case XMLRPC_TYPE_DEAD
:
72 XMLRPC_ASSERT(FALSE
); /* Can't happen, per entry conditions */
75 XMLRPC_ASSERT(FALSE
); /* There are no other possible values */
78 /* Next, we mark this value as invalid, to help catch refcount
80 valueP
->_type
= XMLRPC_TYPE_DEAD
;
82 /* Finally, we destroy the value itself. */
88 /*=========================================================================
90 **=========================================================================
91 ** Some simple reference-counting code. The xmlrpc_DECREF routine is in
92 ** charge of destroying values when their reference count equals zero.
96 xmlrpc_INCREF (xmlrpc_value
* const valueP
) {
98 XMLRPC_ASSERT_VALUE_OK(valueP
);
99 XMLRPC_ASSERT(valueP
->_refcount
> 0);
107 xmlrpc_DECREF (xmlrpc_value
* const valueP
) {
109 XMLRPC_ASSERT_VALUE_OK(valueP
);
110 XMLRPC_ASSERT(valueP
->_refcount
> 0);
111 XMLRPC_ASSERT(valueP
->_type
!= XMLRPC_TYPE_DEAD
);
115 /* If we have no more refs, we need to deallocate this value. */
116 if (valueP
->_refcount
== 0)
117 destroyValue(valueP
);
122 /*=========================================================================
124 =========================================================================*/
127 typeName(xmlrpc_type
const type
) {
131 case XMLRPC_TYPE_INT
: return "INT";
132 case XMLRPC_TYPE_BOOL
: return "BOOL";
133 case XMLRPC_TYPE_DOUBLE
: return "DOUBLE";
134 case XMLRPC_TYPE_DATETIME
: return "DATETIME";
135 case XMLRPC_TYPE_STRING
: return "STRING";
136 case XMLRPC_TYPE_BASE64
: return "BASE64";
137 case XMLRPC_TYPE_ARRAY
: return "ARRAY";
138 case XMLRPC_TYPE_STRUCT
: return "STRUCT";
139 case XMLRPC_TYPE_C_PTR
: return "C_PTR";
140 case XMLRPC_TYPE_DEAD
: return "DEAD";
141 default: return "???";
148 verifyNoNulls(xmlrpc_env
* const envP
,
149 const char * const contents
,
150 unsigned int const len
) {
151 /*----------------------------------------------------------------------------
152 Verify that the character array 'contents', which is 'len' bytes long,
153 does not contain any NUL characters, which means it can be made into
154 a passable ASCIIZ string just by adding a terminating NUL.
156 Fail if the array contains a NUL.
157 -----------------------------------------------------------------------------*/
160 for (i
= 0; i
< len
&& !envP
->fault_occurred
; i
++)
161 if (contents
[i
] == '\0')
162 xmlrpc_env_set_fault_formatted(
163 envP
, XMLRPC_TYPE_ERROR
,
164 "String must not contain NUL characters");
170 verifyNoNullsW(xmlrpc_env
* const envP
,
171 const wchar_t * const contents
,
172 unsigned int const len
) {
173 /*----------------------------------------------------------------------------
174 Same as verifyNoNulls(), but for wide characters.
175 -----------------------------------------------------------------------------*/
178 for (i
= 0; i
< len
&& !envP
->fault_occurred
; i
++)
179 if (contents
[i
] == '\0')
180 xmlrpc_env_set_fault_formatted(
181 envP
, XMLRPC_TYPE_ERROR
,
182 "String must not contain NUL characters");
188 validateType(xmlrpc_env
* const envP
,
189 const xmlrpc_value
* const valueP
,
190 xmlrpc_type
const expectedType
) {
192 if (valueP
->_type
!= expectedType
) {
193 xmlrpc_env_set_fault_formatted(
194 envP
, XMLRPC_TYPE_ERROR
, "Value of type %s supplied where "
195 "type %s was expected.",
196 typeName(valueP
->_type
), typeName(expectedType
));
202 /*=========================================================================
203 Extracting XML-RPC value
204 ===========================================================================
205 These routines extract XML-RPC values into ordinary C data types.
207 For array and struct values, see the separates files xmlrpc_array.c
209 =========================================================================*/
212 xmlrpc_read_int(xmlrpc_env
* const envP
,
213 const xmlrpc_value
* const valueP
,
214 xmlrpc_int32
* const intValueP
) {
216 validateType(envP
, valueP
, XMLRPC_TYPE_INT
);
217 if (!envP
->fault_occurred
)
218 *intValueP
= valueP
->_value
.i
;
224 xmlrpc_read_double(xmlrpc_env
* const envP
,
225 const xmlrpc_value
* const valueP
,
226 xmlrpc_double
* const doubleValueP
) {
228 validateType(envP
, valueP
, XMLRPC_TYPE_DOUBLE
);
229 if (!envP
->fault_occurred
)
230 *doubleValueP
= valueP
->_value
.d
;
237 xmlrpc_read_bool(xmlrpc_env
* const envP
,
238 const xmlrpc_value
* const valueP
,
239 xmlrpc_bool
* const boolValueP
) {
241 validateType(envP
, valueP
, XMLRPC_TYPE_BOOL
);
242 if (!envP
->fault_occurred
)
243 *boolValueP
= valueP
->_value
.b
;
249 xmlrpc_read_string(xmlrpc_env
* const envP
,
250 const xmlrpc_value
* const valueP
,
251 const char ** const stringValueP
) {
252 /*----------------------------------------------------------------------------
253 Read the value of an XML-RPC string an ASCIIZ string.
255 Fail if the string contains null characters (which means it wasn't
256 really a string, but XML-RPC doesn't seem to understand what a string
257 is, and such values are possible).
258 -----------------------------------------------------------------------------*/
259 validateType(envP
, valueP
, XMLRPC_TYPE_STRING
);
260 if (!envP
->fault_occurred
) {
262 XMLRPC_MEMBLOCK_SIZE(char, &valueP
->_block
);
263 const char * const contents
=
264 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP
->_block
);
266 verifyNoNulls(envP
, contents
, (unsigned int)size
);
267 if (!envP
->fault_occurred
) {
270 stringValue
= malloc(size
+1);
271 if (stringValue
== NULL
)
272 xmlrpc_env_set_fault_formatted(
273 envP
, XMLRPC_INTERNAL_ERROR
, "Unable to allocate space "
274 "for %u-character string", size
);
277 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP
->_block
), size
);
278 stringValue
[size
] = '\0';
280 *stringValueP
= stringValue
;
289 xmlrpc_read_string_lp(xmlrpc_env
* const envP
,
290 const xmlrpc_value
* const valueP
,
291 unsigned int * const lengthP
,
292 const char ** const stringValueP
) {
294 validateType(envP
, valueP
, XMLRPC_TYPE_STRING
);
295 if (!envP
->fault_occurred
) {
297 XMLRPC_MEMBLOCK_SIZE(char, &valueP
->_block
);
298 const char * const contents
=
299 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP
->_block
);
303 stringValue
= malloc(size
);
304 if (stringValue
== NULL
)
305 xmlrpc_env_set_fault_formatted(
306 envP
, XMLRPC_INTERNAL_ERROR
, "Unable to allocate %u bytes "
307 "for string.", size
);
309 memcpy(stringValue
, contents
, size
);
310 *stringValueP
= stringValue
;
311 *lengthP
= (unsigned int)size
;
318 /*=========================================================================
319 ** Building XML-RPC values.
320 **=========================================================================
321 ** Build new XML-RPC values from a format string. This code is heavily
322 ** inspired by Py_BuildValue from Python 1.5.2. In particular, our
323 ** particular abuse of the va_list data type is copied from the equivalent
324 ** Python code in modsupport.c. Since Python is portable, our code should
325 ** (in theory) also be portable.
329 xmlrpc_type
xmlrpc_value_type (xmlrpc_value
* value
)
331 XMLRPC_ASSERT_VALUE_OK(value
);
338 createXmlrpcValue(xmlrpc_env
* const envP
,
339 xmlrpc_value
** const valPP
) {
340 /*----------------------------------------------------------------------------
341 Create a blank xmlrpc_value to be filled in.
343 Set the reference count to 1.
344 -----------------------------------------------------------------------------*/
347 valP
= (xmlrpc_value
*) malloc(sizeof(xmlrpc_value
));
349 xmlrpc_env_set_fault(envP
, XMLRPC_INTERNAL_ERROR
,
350 "Could not allocate memory for xmlrpc_value");
360 mkInt(xmlrpc_env
* const envP
,
361 xmlrpc_int32
const value
,
362 xmlrpc_value
** const valPP
) {
366 createXmlrpcValue(envP
, &valP
);
368 if (!envP
->fault_occurred
) {
369 valP
->_type
= XMLRPC_TYPE_INT
;
370 valP
->_value
.i
= value
;
378 mkBool(xmlrpc_env
* const envP
,
379 xmlrpc_bool
const value
,
380 xmlrpc_value
** const valPP
) {
384 createXmlrpcValue(envP
, &valP
);
386 if (!envP
->fault_occurred
) {
387 valP
->_type
= XMLRPC_TYPE_BOOL
;
388 valP
->_value
.b
= value
;
396 mkDouble(xmlrpc_env
* const envP
,
398 xmlrpc_value
** const valPP
) {
402 createXmlrpcValue(envP
, &valP
);
404 if (!envP
->fault_occurred
) {
405 valP
->_type
= XMLRPC_TYPE_DOUBLE
;
406 valP
->_value
.d
= value
;
413 #ifdef HAVE_UNICODE_WCHAR
414 #define MAKE_WCS_BLOCK_NULL(val) ((val)->_wcs_block = NULL)
416 #define MAKE_WCS_BLOCK_NULL(val) do {} while(0)
422 mkString(xmlrpc_env
* const envP
,
423 const char * const value
,
424 unsigned int const length
,
425 xmlrpc_value
** const valPP
) {
429 createXmlrpcValue(envP
, &valP
);
431 if (!envP
->fault_occurred
) {
432 valP
->_type
= XMLRPC_TYPE_STRING
;
433 MAKE_WCS_BLOCK_NULL(valP
);
434 XMLRPC_MEMBLOCK_INIT(char, envP
, &valP
->_block
, length
+ 1);
435 if (!envP
->fault_occurred
) {
436 char * const contents
=
437 XMLRPC_MEMBLOCK_CONTENTS(char, &valP
->_block
);
438 memcpy(contents
, value
, length
);
439 contents
[length
] = '\0';
441 if (envP
->fault_occurred
)
450 getString(xmlrpc_env
* const envP
,
451 const char ** const formatP
,
452 va_list * const args
,
453 xmlrpc_value
** const valPP
) {
458 str
= (const char*) va_arg(*args
, char*);
459 if (**formatP
== '#') {
461 len
= (size_t) va_arg(*args
, size_t);
465 mkString(envP
, str
, (unsigned int)len
, valPP
);
470 #ifdef HAVE_UNICODE_WCHAR
472 mkWideString(xmlrpc_env
* const envP
,
474 size_t const wcs_len
,
475 xmlrpc_value
** const valPP
) {
479 wchar_t *wcs_contents
;
481 xmlrpc_mem_block
*utf8_block
;
485 /* Error-handling preconditions. */
489 /* Initialize our XML-RPC value. */
490 valP
= (xmlrpc_value
*) malloc(sizeof(xmlrpc_value
));
491 XMLRPC_FAIL_IF_NULL(valP
, envP
, XMLRPC_INTERNAL_ERROR
,
492 "Could not allocate memory for wide string");
494 valP
->_type
= XMLRPC_TYPE_STRING
;
496 /* More error-handling preconditions. */
497 valP
->_wcs_block
= NULL
;
499 /* Build our wchar_t block first. */
501 XMLRPC_TYPED_MEM_BLOCK_NEW(wchar_t, envP
, wcs_len
+ 1);
502 XMLRPC_FAIL_IF_FAULT(envP
);
504 XMLRPC_TYPED_MEM_BLOCK_CONTENTS(wchar_t, valP
->_wcs_block
);
505 memcpy(wcs_contents
, wcs
, wcs_len
* sizeof(wchar_t));
506 wcs_contents
[wcs_len
] = '\0';
508 /* Convert the wcs block to UTF-8. */
509 utf8_block
= xmlrpc_wcs_to_utf8(envP
, wcs_contents
, wcs_len
+ 1);
510 XMLRPC_FAIL_IF_FAULT(envP
);
511 utf8_contents
= XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, utf8_block
);
512 utf8_len
= XMLRPC_TYPED_MEM_BLOCK_SIZE(char, utf8_block
);
514 /* XXX - We need an extra memcopy to initialize _block. */
515 XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP
, &valP
->_block
, utf8_len
);
516 XMLRPC_FAIL_IF_FAULT(envP
);
518 contents
= XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP
->_block
);
519 memcpy(contents
, utf8_contents
, utf8_len
);
523 xmlrpc_mem_block_free(utf8_block
);
524 if (envP
->fault_occurred
) {
526 if (valP
->_wcs_block
)
527 xmlrpc_mem_block_free(valP
->_wcs_block
);
529 xmlrpc_mem_block_clean(&valP
->_block
);
535 #endif /* HAVE_UNICODE_WCHAR */
540 getWideString(xmlrpc_env
* const envP
,
541 const char ** const formatP
,
542 va_list * const args
,
543 xmlrpc_value
** const valPP
) {
544 #ifdef HAVE_UNICODE_WCHAR
549 wcs
= (wchar_t*) va_arg(*args
, wchar_t*);
550 if (**formatP
== '#') {
552 len
= (size_t) va_arg(*args
, size_t);
556 mkWideString(envP
, wcs
, len
, valPP
);
558 #endif /* HAVE_UNICODE_WCHAR */
564 mkDatetime(xmlrpc_env
* const envP
,
565 const char * const value
,
566 xmlrpc_value
** const valPP
) {
570 createXmlrpcValue(envP
, &valP
);
572 if (!envP
->fault_occurred
) {
573 valP
->_type
= XMLRPC_TYPE_DATETIME
;
575 XMLRPC_TYPED_MEM_BLOCK_INIT(
576 char, envP
, &valP
->_block
, strlen(value
) + 1);
577 if (!envP
->fault_occurred
) {
578 char * const contents
=
579 XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, &valP
->_block
);
580 strcpy(contents
, value
);
582 if (envP
->fault_occurred
)
591 mkBase64(xmlrpc_env
* const envP
,
592 const unsigned char * const value
,
594 xmlrpc_value
** const valPP
) {
598 createXmlrpcValue(envP
, &valP
);
600 if (!envP
->fault_occurred
) {
601 valP
->_type
= XMLRPC_TYPE_BASE64
;
603 xmlrpc_mem_block_init(envP
, &valP
->_block
, length
);
604 if (!envP
->fault_occurred
) {
605 char * const contents
=
606 xmlrpc_mem_block_contents(&valP
->_block
);
607 memcpy(contents
, value
, length
);
609 if (envP
->fault_occurred
)
618 getBase64(xmlrpc_env
* const envP
,
619 va_list * const args
,
620 xmlrpc_value
** const valPP
) {
622 unsigned char * value
;
625 value
= (unsigned char*) va_arg(*args
, unsigned char*);
626 length
= (size_t) va_arg(*args
, size_t);
628 mkBase64(envP
, value
, length
, valPP
);
634 mkCPtr(xmlrpc_env
* const envP
,
636 xmlrpc_value
** const valPP
) {
640 createXmlrpcValue(envP
, &valP
);
642 if (!envP
->fault_occurred
) {
643 valP
->_type
= XMLRPC_TYPE_C_PTR
;
644 valP
->_value
.c_ptr
= value
;
652 mkArrayFromVal(xmlrpc_env
* const envP
,
653 xmlrpc_value
* const value
,
654 xmlrpc_value
** const valPP
) {
656 if (xmlrpc_value_type(value
) != XMLRPC_TYPE_ARRAY
)
657 xmlrpc_env_set_fault(envP
, XMLRPC_INTERNAL_ERROR
,
658 "Array format ('A'), non-array xmlrpc_value");
660 xmlrpc_INCREF(value
);
668 mkStructFromVal(xmlrpc_env
* const envP
,
669 xmlrpc_value
* const value
,
670 xmlrpc_value
** const valPP
) {
672 if (xmlrpc_value_type(value
) != XMLRPC_TYPE_STRUCT
)
673 xmlrpc_env_set_fault(envP
, XMLRPC_INTERNAL_ERROR
,
674 "Struct format ('S'), non-struct xmlrpc_value");
676 xmlrpc_INCREF(value
);
684 getValue(xmlrpc_env
* const envP
,
685 const char** const format
,
686 va_list * const args
,
687 xmlrpc_value
** const valPP
);
692 createXmlrpcArray(xmlrpc_env
* const envP
,
693 xmlrpc_value
** const arrayPP
) {
694 /*----------------------------------------------------------------------------
695 Create an empty array xmlrpc_value.
696 -----------------------------------------------------------------------------*/
697 xmlrpc_value
* arrayP
;
699 createXmlrpcValue(envP
, &arrayP
);
700 if (!envP
->fault_occurred
) {
701 arrayP
->_type
= XMLRPC_TYPE_ARRAY
;
702 XMLRPC_TYPED_MEM_BLOCK_INIT(xmlrpc_value
*, envP
, &arrayP
->_block
, 0);
703 if (envP
->fault_occurred
)
712 getArray(xmlrpc_env
* const envP
,
713 const char ** const formatP
,
714 char const delimiter
,
715 va_list * const args
,
716 xmlrpc_value
** const arrayPP
) {
718 xmlrpc_value
* arrayP
;
720 createXmlrpcArray(envP
, &arrayP
);
722 /* Add items to the array until we hit our delimiter. */
724 while (**formatP
!= delimiter
&& !envP
->fault_occurred
) {
726 xmlrpc_value
* itemP
;
728 if (**formatP
== '\0')
729 xmlrpc_env_set_fault(
730 envP
, XMLRPC_INTERNAL_ERROR
,
731 "format string ended before closing ')'.");
733 getValue(envP
, formatP
, args
, &itemP
);
734 if (!envP
->fault_occurred
) {
735 xmlrpc_array_append_item(envP
, arrayP
, itemP
);
736 xmlrpc_DECREF(itemP
);
740 if (envP
->fault_occurred
)
741 xmlrpc_DECREF(arrayP
);
749 getStructMember(xmlrpc_env
* const envP
,
750 const char ** const formatP
,
751 va_list * const args
,
752 xmlrpc_value
** const keyPP
,
753 xmlrpc_value
** const valuePP
) {
757 getValue(envP
, formatP
, args
, keyPP
);
758 if (!envP
->fault_occurred
) {
759 if (**formatP
!= ':')
760 xmlrpc_env_set_fault(
761 envP
, XMLRPC_INTERNAL_ERROR
,
762 "format string does not have ':' after a "
763 "structure member key.");
765 /* Skip over colon that separates key from value */
769 getValue(envP
, formatP
, args
, valuePP
);
771 if (envP
->fault_occurred
)
772 xmlrpc_DECREF(*keyPP
);
779 getStruct(xmlrpc_env
* const envP
,
780 const char ** const formatP
,
781 char const delimiter
,
782 va_list * const args
,
783 xmlrpc_value
** const structPP
) {
785 xmlrpc_value
* structP
;
787 structP
= xmlrpc_struct_new(envP
);
788 if (!envP
->fault_occurred
) {
789 while (**formatP
!= delimiter
&& !envP
->fault_occurred
) {
791 xmlrpc_value
* valueP
;
793 getStructMember(envP
, formatP
, args
, &keyP
, &valueP
);
795 if (!envP
->fault_occurred
) {
796 if (**formatP
== ',')
797 (*formatP
)++; /* Skip over the comma */
798 else if (**formatP
== delimiter
) {
799 /* End of the line */
801 xmlrpc_env_set_fault(
802 envP
, XMLRPC_INTERNAL_ERROR
,
803 "format string does not have ',' or ')' after "
804 "a structure member");
806 if (!envP
->fault_occurred
)
807 /* Add the new member to the struct. */
808 xmlrpc_struct_set_value_v(envP
, structP
, keyP
, valueP
);
810 xmlrpc_DECREF(valueP
);
814 if (envP
->fault_occurred
)
815 xmlrpc_DECREF(structP
);
823 getValue(xmlrpc_env
* const envP
,
824 const char** const formatP
,
825 va_list * const args
,
826 xmlrpc_value
** const valPP
) {
827 /*----------------------------------------------------------------------------
828 Get the next value from the list. *formatP points to the specifier
829 for the next value in the format string (i.e. to the type code
830 character) and we move *formatP past the whole specifier for the
831 next value. We read the required arguments from 'args'. We return
832 the value as *valPP with a reference to it.
834 For example, if *formatP points to the "i" in the string "sis",
835 we read one argument from 'args' and return as *valP an integer whose
836 value is the argument we read. We advance *formatP to point to the
837 last 's' and advance 'args' to point to the argument that belongs to
839 -----------------------------------------------------------------------------*/
840 char const formatChar
= *(*formatP
)++;
842 switch (formatChar
) {
844 mkInt(envP
, (xmlrpc_int32
) va_arg(*args
, xmlrpc_int32
), valPP
);
848 mkBool(envP
, (xmlrpc_bool
) va_arg(*args
, xmlrpc_bool
), valPP
);
852 mkDouble(envP
, (double) va_arg(*args
, va_double
), valPP
);
856 getString(envP
, formatP
, args
, valPP
);
860 getWideString(envP
, formatP
, args
, valPP
);
863 /* The code 't' is reserved for a better, time_t based
864 implementation of dateTime conversion.
867 mkDatetime(envP
, (char*) va_arg(*args
, char*), valPP
);
871 getBase64(envP
, args
, valPP
);
875 /* We might someday want to use the code 'p!' to read in a
876 cleanup function for this pointer.
878 mkCPtr(envP
, (void*) va_arg(*args
, void*), valPP
);
882 mkArrayFromVal(envP
, (xmlrpc_value
*) va_arg(*args
, xmlrpc_value
*),
887 mkStructFromVal(envP
, (xmlrpc_value
*) va_arg(*args
, xmlrpc_value
*),
892 *valPP
= (xmlrpc_value
*) va_arg(*args
, xmlrpc_value
*);
893 xmlrpc_INCREF(*valPP
);
897 getArray(envP
, formatP
, ')', args
, valPP
);
898 if (!envP
->fault_occurred
) {
899 XMLRPC_ASSERT(**formatP
== ')');
900 (*formatP
)++; /* Skip over closing parenthesis */
905 getStruct(envP
, formatP
, '}', args
, valPP
);
906 if (!envP
->fault_occurred
) {
907 XMLRPC_ASSERT(**formatP
== '}');
908 (*formatP
)++; /* Skip over closing brace */
913 const char * const badCharacter
= xmlrpc_makePrintableChar(formatChar
);
914 xmlrpc_env_set_fault_formatted(
915 envP
, XMLRPC_INTERNAL_ERROR
,
916 "Unexpected character '%s' in format string", badCharacter
);
917 xmlrpc_strfree(badCharacter
);
925 xmlrpc_build_value_va(xmlrpc_env
* const envP
,
926 const char * const format
,
928 xmlrpc_value
** const valPP
,
929 const char ** const tailP
) {
931 const char * formatCursor
;
934 XMLRPC_ASSERT_ENV_OK(envP
);
935 XMLRPC_ASSERT(format
!= NULL
);
937 if (strlen(format
) == 0)
938 xmlrpc_env_set_fault_formatted(
939 envP
, XMLRPC_INTERNAL_ERROR
, "Format string is empty.");
941 formatCursor
= &format
[0];
942 VA_LIST_COPY(args_copy
, args
);
943 getValue(envP
, &formatCursor
, &args_copy
, valPP
);
945 if (!envP
->fault_occurred
)
946 XMLRPC_ASSERT_VALUE_OK(*valPP
);
948 *tailP
= formatCursor
;
955 xmlrpc_build_value(xmlrpc_env
* const envP
,
956 const char * const format
,
960 xmlrpc_value
* retval
;
963 va_start(args
, format
);
964 xmlrpc_build_value_va(envP
, format
, args
, &retval
, &suffix
);
967 if (!envP
->fault_occurred
) {
969 xmlrpc_env_set_fault_formatted(
970 envP
, XMLRPC_INTERNAL_ERROR
, "Junk after the argument "
971 "specifier: '%s'. There must be exactly one arument.",
974 if (envP
->fault_occurred
)
975 xmlrpc_DECREF(retval
);
981 /*=========================================================================
982 ** Parsing XML-RPC values.
983 **=========================================================================
984 ** Parse an XML-RPC value based on a format string. This code is heavily
985 ** inspired by Py_BuildValue from Python 1.5.2.
988 /* Prototype for recursive invocation: */
991 parsevalue(xmlrpc_env
* const env
,
992 xmlrpc_value
* const val
,
993 const char ** const format
,
997 parsearray(xmlrpc_env
* const env
,
998 const xmlrpc_value
* const array
,
999 const char ** const format
,
1000 char const delimiter
,
1006 /* Fetch the array size. */
1007 size
= xmlrpc_array_size(env
, array
);
1008 XMLRPC_FAIL_IF_FAULT(env
);
1010 /* Loop over the items in the array. */
1011 for (i
= 0; i
< size
; i
++) {
1012 /* Bail out if the caller didn't care about the rest of the items. */
1013 if (**format
== '*')
1016 item
= xmlrpc_array_get_item(env
, array
, i
);
1017 XMLRPC_FAIL_IF_FAULT(env
);
1019 XMLRPC_ASSERT(**format
!= '\0');
1020 if (**format
== delimiter
)
1021 XMLRPC_FAIL(env
, XMLRPC_INDEX_ERROR
, "Too many items in array");
1022 parsevalue(env
, item
, format
, args
);
1023 XMLRPC_FAIL_IF_FAULT(env
);
1025 if (**format
== '*')
1027 if (**format
!= delimiter
)
1028 XMLRPC_FAIL(env
, XMLRPC_INDEX_ERROR
, "Not enough items in array");
1037 parsestruct(xmlrpc_env
* const env
,
1038 xmlrpc_value
* const strct
,
1039 const char ** const format
,
1040 char const delimiter
,
1043 xmlrpc_value
*key
, *value
;
1047 /* Set up error handling preconditions. */
1050 /* Build the members of our struct. */
1051 while (**format
!= '*' && **format
!= delimiter
&& **format
!= '\0') {
1053 /* Get our key, and skip over the ':' character. Notice the
1054 ** sudden call to getValue--we're going in the opposite direction. */
1055 getValue(env
, format
, args
, &key
);
1056 XMLRPC_FAIL_IF_FAULT(env
);
1057 XMLRPC_ASSERT(**format
== ':');
1060 /* Look up the value for our key. */
1061 xmlrpc_parse_value(env
, key
, "s#", &keystr
, &keylen
);
1062 XMLRPC_FAIL_IF_FAULT(env
);
1063 value
= xmlrpc_struct_get_value_n(env
, strct
, keystr
, keylen
);
1064 XMLRPC_FAIL_IF_FAULT(env
);
1066 /* Get our value, and skip over the ',' character (if present). */
1067 parsevalue(env
, value
, format
, args
);
1068 XMLRPC_FAIL_IF_FAULT(env
);
1069 XMLRPC_ASSERT(**format
== ',' || **format
== delimiter
);
1070 if (**format
== ',')
1073 /* Release our reference, and restore our invariant. */
1077 if (**format
== '*') {
1079 if (**format
!= delimiter
&& **format
!= '\0')
1080 XMLRPC_FAIL(env
, XMLRPC_INTERNAL_ERROR
,
1081 "* can appear only at the end "
1082 "of a structure format specifier");
1084 /* Here we're supposed to fail if he didn't extract all the
1085 members. But we don't know how to determine whether he
1086 specified all the members, so we always fail.
1088 XMLRPC_FAIL(env
, XMLRPC_INTERNAL_ERROR
, "You must specify '*' as the "
1089 "last member of a structure in a format specifier "
1090 "used for parsing an xmlrpc_value");
1092 XMLRPC_ASSERT(**format
== delimiter
|| **format
== '\0');
1101 parsevalue(xmlrpc_env
* const envP
,
1102 xmlrpc_value
* const valueP
,
1103 const char ** const format
,
1106 char formatSpecChar
;
1108 formatSpecChar
= *(*format
)++;
1110 switch (formatSpecChar
) {
1112 validateType(envP
, valueP
, XMLRPC_TYPE_INT
);
1113 if (!envP
->fault_occurred
) {
1114 xmlrpc_int32
* const int32ptr
=
1115 (xmlrpc_int32
*) va_arg(*args
, xmlrpc_int32
*);
1116 *int32ptr
= valueP
->_value
.i
;
1121 validateType(envP
, valueP
, XMLRPC_TYPE_BOOL
);
1122 if (!envP
->fault_occurred
) {
1123 xmlrpc_bool
* const boolptr
=
1124 (xmlrpc_bool
*) va_arg(*args
, xmlrpc_bool
*);
1125 *boolptr
= valueP
->_value
.b
;
1130 validateType(envP
, valueP
, XMLRPC_TYPE_DOUBLE
);
1131 if (!envP
->fault_occurred
) {
1132 double * const doubleptr
= (double*) va_arg(*args
, double*);
1133 *doubleptr
= valueP
->_value
.d
;
1138 validateType(envP
, valueP
, XMLRPC_TYPE_STRING
);
1139 if (!envP
->fault_occurred
) {
1140 char * const contents
=
1141 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP
->_block
);
1142 size_t const len
= XMLRPC_MEMBLOCK_SIZE(char, &valueP
->_block
) - 1;
1144 char ** const strptr
= (char**) va_arg(*args
, char**);
1145 if (**format
== '#') {
1146 size_t * const sizeptr
= (size_t*) va_arg(*args
, size_t**);
1150 verifyNoNulls(envP
, contents
, (unsigned int)len
);
1155 #ifdef HAVE_UNICODE_WCHAR
1157 validateType(envP
, valueP
, XMLRPC_TYPE_STRING
);
1158 if (!envP
->fault_occurred
) {
1159 if (!valueP
->_wcs_block
) {
1160 /* Allocate a wchar_t string if we don't have one. */
1161 char * const contents
=
1162 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP
->_block
);
1164 XMLRPC_MEMBLOCK_SIZE(char, &valueP
->_block
) - 1;
1165 valueP
->_wcs_block
=
1166 xmlrpc_utf8_to_wcs(envP
, contents
, len
+ 1);
1168 if (!envP
->fault_occurred
) {
1169 wchar_t * const wcontents
=
1170 XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP
->_wcs_block
);
1172 XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP
->_wcs_block
) - 1;
1174 wchar_t ** const wcsptr
= (wchar_t**) va_arg(*args
, wchar_t**);
1175 if (**format
== '#') {
1176 size_t * const sizeptr
= (size_t*) va_arg(*args
, size_t**);
1180 verifyNoNullsW(envP
, wcontents
, (unsigned int)len
);
1181 *wcsptr
= wcontents
;
1185 #endif /* HAVE_UNICODE_WCHAR */
1188 /* The code 't' is reserved for a better, time_t based
1189 ** implementation of dateTime conversion. */
1190 validateType(envP
, valueP
, XMLRPC_TYPE_DATETIME
);
1191 if (!envP
->fault_occurred
) {
1192 char * const contents
=
1193 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP
->_block
);
1194 char ** const strptr
= (char**) va_arg(*args
, char**);
1200 validateType(envP
, valueP
, XMLRPC_TYPE_BASE64
);
1201 if (!envP
->fault_occurred
) {
1202 unsigned char * const bin_data
=
1203 XMLRPC_MEMBLOCK_CONTENTS(unsigned char,
1205 size_t const len
= XMLRPC_MEMBLOCK_SIZE(char, &valueP
->_block
);
1206 unsigned char ** const binptr
=
1207 (unsigned char**) va_arg(*args
, unsigned char**);
1208 size_t * const sizeptr
= (size_t*) va_arg(*args
, size_t**);
1215 validateType(envP
, valueP
, XMLRPC_TYPE_C_PTR
);
1216 if (!envP
->fault_occurred
) {
1217 void ** const voidptrptr
= (void**) va_arg(*args
, void**);
1218 *voidptrptr
= valueP
->_value
.c_ptr
;
1223 xmlrpc_value
** const valptr
=
1224 (xmlrpc_value
**) va_arg(*args
, xmlrpc_value
**);
1230 validateType(envP
, valueP
, XMLRPC_TYPE_ARRAY
);
1231 if (!envP
->fault_occurred
) {
1232 xmlrpc_value
** const valptr
=
1233 (xmlrpc_value
**) va_arg(*args
, xmlrpc_value
**);
1239 validateType(envP
, valueP
, XMLRPC_TYPE_STRUCT
);
1240 if (!envP
->fault_occurred
) {
1241 xmlrpc_value
** const valptr
=
1242 (xmlrpc_value
**) va_arg(*args
, xmlrpc_value
**);
1248 validateType(envP
, valueP
, XMLRPC_TYPE_ARRAY
);
1249 if (!envP
->fault_occurred
) {
1250 parsearray(envP
, valueP
, format
, ')', args
);
1256 validateType(envP
, valueP
, XMLRPC_TYPE_STRUCT
);
1257 if (!envP
->fault_occurred
) {
1258 parsestruct(envP
, valueP
, format
, '}', args
);
1264 xmlrpc_env_set_fault_formatted(
1265 envP
, XMLRPC_INTERNAL_ERROR
, "Invalid format character '%c'",
1273 xmlrpc_parse_value_va(xmlrpc_env
* const envP
,
1274 xmlrpc_value
* const value
,
1275 const char * const format
,
1278 const char *format_copy
;
1281 XMLRPC_ASSERT_ENV_OK(envP
);
1282 XMLRPC_ASSERT_VALUE_OK(value
);
1283 XMLRPC_ASSERT(format
!= NULL
);
1285 format_copy
= format
;
1286 VA_LIST_COPY(args_copy
, args
);
1287 parsevalue(envP
, value
, &format_copy
, &args_copy
);
1288 if (!envP
->fault_occurred
) {
1289 XMLRPC_ASSERT(*format_copy
== '\0');
1296 xmlrpc_parse_value(xmlrpc_env
* const envP
,
1297 xmlrpc_value
* const value
,
1298 const char * const format
,
1303 va_start(args
, format
);
1304 xmlrpc_parse_value_va(envP
, value
, format
, args
);
1310 /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
1311 ** Copyright (C) 2001 by Eric Kidd. All rights reserved.
1313 ** Redistribution and use in source and binary forms, with or without
1314 ** modification, are permitted provided that the following conditions
1316 ** 1. Redistributions of source code must retain the above copyright
1317 ** notice, this list of conditions and the following disclaimer.
1318 ** 2. Redistributions in binary form must reproduce the above copyright
1319 ** notice, this list of conditions and the following disclaimer in the
1320 ** documentation and/or other materials provided with the distribution.
1321 ** 3. The name of the author may not be used to endorse or promote products
1322 ** derived from this software without specific prior written permission.
1324 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1325 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1326 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1327 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1328 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1329 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1330 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1331 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1332 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1333 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF