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