1 /* Copyright information is at end of file */
3 #include "xmlrpc_config.h"
11 #include "mallocvar.h"
13 #include "xmlrpc-c/base.h"
14 #include "xmlrpc-c/base_int.h"
19 destroyValue(xmlrpc_value * const valueP) {
21 /* First, we need to destroy this value's contents, if any. */
22 switch (valueP->_type) {
26 case XMLRPC_TYPE_BOOL:
29 case XMLRPC_TYPE_DOUBLE:
32 case XMLRPC_TYPE_DATETIME:
33 xmlrpc_mem_block_clean(&valueP->_block);
36 case XMLRPC_TYPE_STRING:
37 if (valueP->_wcs_block)
38 xmlrpc_mem_block_free(valueP->_wcs_block);
39 xmlrpc_mem_block_clean(&valueP->_block);
42 case XMLRPC_TYPE_BASE64:
43 xmlrpc_mem_block_clean(&valueP->_block);
46 case XMLRPC_TYPE_ARRAY:
47 xmlrpc_destroyArrayContents(valueP);
50 case XMLRPC_TYPE_STRUCT:
51 xmlrpc_destroyStruct(valueP);
54 case XMLRPC_TYPE_C_PTR:
60 case XMLRPC_TYPE_DEAD:
61 XMLRPC_ASSERT(false); /* Can't happen, per entry conditions */
64 XMLRPC_ASSERT(false); /* There are no other possible values */
67 /* Next, we mark this value as invalid, to help catch refcount
69 valueP->_type = XMLRPC_TYPE_DEAD;
71 /* Finally, we destroy the value itself. */
77 /*=========================================================================
79 **=========================================================================
80 ** Some simple reference-counting code. The xmlrpc_DECREF routine is in
81 ** charge of destroying values when their reference count equals zero.
85 xmlrpc_INCREF (xmlrpc_value * const valueP) {
87 XMLRPC_ASSERT_VALUE_OK(valueP);
88 XMLRPC_ASSERT(valueP->_refcount > 0);
96 xmlrpc_DECREF (xmlrpc_value * const valueP) {
98 XMLRPC_ASSERT_VALUE_OK(valueP);
99 XMLRPC_ASSERT(valueP->_refcount > 0);
100 XMLRPC_ASSERT(valueP->_type != XMLRPC_TYPE_DEAD);
104 /* If we have no more refs, we need to deallocate this value. */
105 if (valueP->_refcount == 0)
106 destroyValue(valueP);
111 /*=========================================================================
113 =========================================================================*/
116 xmlrpc_typeName(xmlrpc_type const type) {
120 case XMLRPC_TYPE_INT: return "INT";
121 case XMLRPC_TYPE_BOOL: return "BOOL";
122 case XMLRPC_TYPE_DOUBLE: return "DOUBLE";
123 case XMLRPC_TYPE_DATETIME: return "DATETIME";
124 case XMLRPC_TYPE_STRING: return "STRING";
125 case XMLRPC_TYPE_BASE64: return "BASE64";
126 case XMLRPC_TYPE_ARRAY: return "ARRAY";
127 case XMLRPC_TYPE_STRUCT: return "STRUCT";
128 case XMLRPC_TYPE_C_PTR: return "C_PTR";
129 case XMLRPC_TYPE_NIL: return "NIL";
130 case XMLRPC_TYPE_DEAD: return "DEAD";
131 default: return "???";
138 verifyNoNulls(xmlrpc_env * const envP,
139 const char * const contents,
140 unsigned int const len) {
141 /*----------------------------------------------------------------------------
142 Verify that the character array 'contents', which is 'len' bytes long,
143 does not contain any NUL characters, which means it can be made into
144 a passable ASCIIZ string just by adding a terminating NUL.
146 Fail if the array contains a NUL.
147 -----------------------------------------------------------------------------*/
150 for (i = 0; i < len && !envP->fault_occurred; i++)
151 if (contents[i] == '\0')
152 xmlrpc_env_set_fault_formatted(
153 envP, XMLRPC_TYPE_ERROR,
154 "String must not contain NUL characters");
159 #if HAVE_UNICODE_WCHAR
162 verifyNoNullsW(xmlrpc_env * const envP,
163 const wchar_t * const contents,
164 unsigned int const len) {
165 /*----------------------------------------------------------------------------
166 Same as verifyNoNulls(), but for wide characters.
167 -----------------------------------------------------------------------------*/
170 for (i = 0; i < len && !envP->fault_occurred; i++)
171 if (contents[i] == '\0')
172 xmlrpc_env_set_fault_formatted(
173 envP, XMLRPC_TYPE_ERROR,
174 "String must not contain NUL characters");
181 validateType(xmlrpc_env * const envP,
182 const xmlrpc_value * const valueP,
183 xmlrpc_type const expectedType) {
185 if (valueP->_type != expectedType) {
186 xmlrpc_env_set_fault_formatted(
187 envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where "
188 "type %s was expected.",
189 xmlrpc_typeName(valueP->_type), xmlrpc_typeName(expectedType));
195 /*=========================================================================
196 Extracting XML-RPC value
197 ===========================================================================
198 These routines extract XML-RPC values into ordinary C data types.
200 For array and struct values, see the separates files xmlrpc_array.c
202 =========================================================================*/
205 xmlrpc_read_int(xmlrpc_env * const envP,
206 const xmlrpc_value * const valueP,
207 xmlrpc_int32 * const intValueP) {
209 validateType(envP, valueP, XMLRPC_TYPE_INT);
210 if (!envP->fault_occurred)
211 *intValueP = valueP->_value.i;
217 xmlrpc_read_bool(xmlrpc_env * const envP,
218 const xmlrpc_value * const valueP,
219 xmlrpc_bool * const boolValueP) {
221 validateType(envP, valueP, XMLRPC_TYPE_BOOL);
222 if (!envP->fault_occurred)
223 *boolValueP = valueP->_value.b;
229 xmlrpc_read_double(xmlrpc_env * const envP,
230 const xmlrpc_value * const valueP,
231 xmlrpc_double * const doubleValueP) {
233 validateType(envP, valueP, XMLRPC_TYPE_DOUBLE);
234 if (!envP->fault_occurred)
235 *doubleValueP = valueP->_value.d;
240 /* datetime stuff is in xmlrpc_datetime.c */
243 accessStringValue(xmlrpc_env * const envP,
244 const xmlrpc_value * const valueP,
245 size_t * const lengthP,
246 const char ** const contentsP) {
248 validateType(envP, valueP, XMLRPC_TYPE_STRING);
249 if (!envP->fault_occurred) {
250 unsigned int const size =
251 XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
252 const char * const contents =
253 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
254 unsigned int const len = size - 1;
255 /* The memblock has a null character added to the end */
257 verifyNoNulls(envP, contents, len);
260 *contentsP = contents;
267 xmlrpc_read_string(xmlrpc_env * const envP,
268 const xmlrpc_value * const valueP,
269 const char ** const stringValueP) {
270 /*----------------------------------------------------------------------------
271 Read the value of an XML-RPC string as an ASCIIZ string.
273 Return the string in newly malloc'ed storage that Caller must free.
275 Fail if the string contains null characters (which means it wasn't
276 really a string, but XML-RPC doesn't seem to understand what a string
277 is, and such values are possible).
278 -----------------------------------------------------------------------------*/
280 const char * contents;
282 accessStringValue(envP, valueP, &length, &contents);
284 if (!envP->fault_occurred) {
287 stringValue = malloc(length+1);
288 if (stringValue == NULL)
289 xmlrpc_env_set_fault_formatted(
290 envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space "
291 "for %u-character string", length);
293 memcpy(stringValue, contents, length);
294 stringValue[length] = '\0';
296 *stringValueP = stringValue;
304 xmlrpc_read_string_old(xmlrpc_env * const envP,
305 const xmlrpc_value * const valueP,
306 const char ** const stringValueP) {
309 accessStringValue(envP, valueP, &length, stringValueP);
315 xmlrpc_read_string_lp(xmlrpc_env * const envP,
316 const xmlrpc_value * const valueP,
317 size_t * const lengthP,
318 const char ** const stringValueP) {
320 validateType(envP, valueP, XMLRPC_TYPE_STRING);
321 if (!envP->fault_occurred) {
322 unsigned int const size =
323 XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
324 const char * const contents =
325 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
329 stringValue = malloc(size);
330 if (stringValue == NULL)
331 xmlrpc_env_set_fault_formatted(
332 envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes "
333 "for string.", size);
335 memcpy(stringValue, contents, size);
336 *stringValueP = stringValue;
337 *lengthP = size - 1; /* Size includes terminating NUL */
345 xmlrpc_read_string_lp_old(xmlrpc_env * const envP,
346 const xmlrpc_value * const valueP,
347 size_t * const lengthP,
348 const char ** const stringValueP) {
350 validateType(envP, valueP, XMLRPC_TYPE_STRING);
351 if (!envP->fault_occurred) {
352 *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
353 *stringValueP = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
359 static __inline__ void
360 setupWcsBlock(xmlrpc_env * const envP,
361 xmlrpc_value * const valueP) {
362 /*----------------------------------------------------------------------------
363 Add a wcs block (wchar_t string) to the indicated xmlrpc_value if it
364 doesn't have one already.
365 -----------------------------------------------------------------------------*/
366 if (!valueP->_wcs_block) {
367 char * const contents =
368 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
370 XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block) - 1;
372 xmlrpc_utf8_to_wcs(envP, contents, len + 1);
378 #if HAVE_UNICODE_WCHAR
381 accessStringValueW(xmlrpc_env * const envP,
382 xmlrpc_value * const valueP,
383 size_t * const lengthP,
384 const wchar_t ** const stringValueP) {
386 validateType(envP, valueP, XMLRPC_TYPE_STRING);
387 if (!envP->fault_occurred) {
388 setupWcsBlock(envP, valueP);
390 if (!envP->fault_occurred) {
391 wchar_t * const wcontents =
392 XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
394 XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block) - 1;
396 verifyNoNullsW(envP, wcontents, len);
399 *stringValueP = wcontents;
407 xmlrpc_read_string_w(xmlrpc_env * const envP,
408 xmlrpc_value * const valueP,
409 const wchar_t ** const stringValueP) {
412 const wchar_t * wcontents;
414 accessStringValueW(envP, valueP, &length, &wcontents);
416 if (!envP->fault_occurred) {
417 wchar_t * stringValue;
418 stringValue = malloc((length + 1) * sizeof(wchar_t));
419 if (stringValue == NULL)
420 xmlrpc_env_set_fault_formatted(
421 envP, XMLRPC_INTERNAL_ERROR,
422 "Unable to allocate space for %u-byte string",
425 memcpy(stringValue, wcontents, length * sizeof(wchar_t));
426 stringValue[length] = '\0';
428 *stringValueP = stringValue;
436 xmlrpc_read_string_w_old(xmlrpc_env * const envP,
437 xmlrpc_value * const valueP,
438 const wchar_t ** const stringValueP) {
442 accessStringValueW(envP, valueP, &length, stringValueP);
448 xmlrpc_read_string_w_lp(xmlrpc_env * const envP,
449 xmlrpc_value * const valueP,
450 size_t * const lengthP,
451 const wchar_t ** const stringValueP) {
453 validateType(envP, valueP, XMLRPC_TYPE_STRING);
454 if (!envP->fault_occurred) {
455 setupWcsBlock(envP, valueP);
457 if (!envP->fault_occurred) {
458 wchar_t * const wcontents =
459 XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
461 XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
463 wchar_t * stringValue;
465 stringValue = malloc(size * sizeof(wchar_t));
466 if (stringValue == NULL)
467 xmlrpc_env_set_fault_formatted(
468 envP, XMLRPC_INTERNAL_ERROR,
469 "Unable to allocate space for %u-byte string",
472 memcpy(stringValue, wcontents, size * sizeof(wchar_t));
474 *lengthP = size - 1; /* size includes terminating NUL */
475 *stringValueP = stringValue;
484 xmlrpc_read_string_w_lp_old(xmlrpc_env * const envP,
485 xmlrpc_value * const valueP,
486 size_t * const lengthP,
487 const wchar_t ** const stringValueP) {
489 validateType(envP, valueP, XMLRPC_TYPE_STRING);
490 if (!envP->fault_occurred) {
491 setupWcsBlock(envP, valueP);
493 if (!envP->fault_occurred) {
494 wchar_t * const wcontents =
495 XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valueP->_wcs_block);
497 XMLRPC_MEMBLOCK_SIZE(wchar_t, valueP->_wcs_block);
499 *lengthP = size - 1; /* size includes terminatnig NUL */
500 *stringValueP = wcontents;
509 xmlrpc_read_base64(xmlrpc_env * const envP,
510 const xmlrpc_value * const valueP,
511 size_t * const lengthP,
512 const unsigned char ** const byteStringValueP) {
514 validateType(envP, valueP, XMLRPC_TYPE_BASE64);
515 if (!envP->fault_occurred) {
517 XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
518 const char * const contents =
519 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
521 char * byteStringValue;
523 byteStringValue = malloc(size);
524 if (byteStringValue == NULL)
525 xmlrpc_env_set_fault_formatted(
526 envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes "
527 "for byte string.", size);
529 memcpy(byteStringValue, contents, size);
530 *byteStringValueP = (const unsigned char *)byteStringValue;
539 xmlrpc_read_base64_old(xmlrpc_env * const envP,
540 const xmlrpc_value * const valueP,
541 size_t * const lengthP,
542 const unsigned char ** const byteStringValueP) {
544 validateType(envP, valueP, XMLRPC_TYPE_BASE64);
545 if (!envP->fault_occurred) {
547 XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
548 *byteStringValueP = (const unsigned char *)
549 XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block);
556 xmlrpc_read_base64_size(xmlrpc_env * const envP,
557 const xmlrpc_value * const valueP,
558 size_t * const lengthP) {
560 validateType(envP, valueP, XMLRPC_TYPE_BASE64);
561 if (!envP->fault_occurred)
562 *lengthP = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block);
568 xmlrpc_read_nil(xmlrpc_env * const envP,
569 xmlrpc_value * const valueP) {
570 /*----------------------------------------------------------------------------
571 Read out the value of a nil value. It doesn't have one, of course, so
572 this is essentially a no-op. But it does validate the type and is
573 necessary to match all the other types.
574 -----------------------------------------------------------------------------*/
575 validateType(envP, valueP, XMLRPC_TYPE_NIL);
581 xmlrpc_read_cptr(xmlrpc_env * const envP,
582 const xmlrpc_value * const valueP,
583 void ** const ptrValueP) {
585 validateType(envP, valueP, XMLRPC_TYPE_C_PTR);
586 if (!envP->fault_occurred)
587 *ptrValueP = valueP->_value.c_ptr;
592 xmlrpc_type xmlrpc_value_type (xmlrpc_value* value)
594 XMLRPC_ASSERT_VALUE_OK(value);
601 xmlrpc_createXmlrpcValue(xmlrpc_env * const envP,
602 xmlrpc_value ** const valPP) {
603 /*----------------------------------------------------------------------------
604 Create a blank xmlrpc_value to be filled in.
606 Set the reference count to 1.
607 -----------------------------------------------------------------------------*/
612 xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
613 "Could not allocate memory for xmlrpc_value");
623 xmlrpc_int_new(xmlrpc_env * const envP,
624 xmlrpc_int32 const value) {
628 xmlrpc_createXmlrpcValue(envP, &valP);
630 if (!envP->fault_occurred) {
631 valP->_type = XMLRPC_TYPE_INT;
632 valP->_value.i = value;
640 xmlrpc_bool_new(xmlrpc_env * const envP,
641 xmlrpc_bool const value) {
645 xmlrpc_createXmlrpcValue(envP, &valP);
647 if (!envP->fault_occurred) {
648 valP->_type = XMLRPC_TYPE_BOOL;
649 valP->_value.b = value;
657 xmlrpc_double_new(xmlrpc_env * const envP,
658 double const value) {
662 xmlrpc_createXmlrpcValue(envP, &valP);
664 if (!envP->fault_occurred) {
665 valP->_type = XMLRPC_TYPE_DOUBLE;
666 valP->_value.d = value;
674 xmlrpc_string_new_lp(xmlrpc_env * const envP,
676 const char * const value) {
680 xmlrpc_createXmlrpcValue(envP, &valP);
682 if (!envP->fault_occurred) {
683 valP->_type = XMLRPC_TYPE_STRING;
684 valP->_wcs_block = NULL;
685 XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, length + 1);
686 if (!envP->fault_occurred) {
687 char * const contents =
688 XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
689 memcpy(contents, value, length);
690 contents[length] = '\0';
692 if (envP->fault_occurred)
701 xmlrpc_string_new(xmlrpc_env * const envP,
702 const char * const value) {
704 return xmlrpc_string_new_lp(envP, strlen(value), value);
708 #if HAVE_UNICODE_WCHAR
710 xmlrpc_string_w_new_lp(xmlrpc_env * const envP,
712 const wchar_t * const value) {
716 /* Initialize our XML-RPC value. */
717 xmlrpc_createXmlrpcValue(envP, &valP);
719 if (!envP->fault_occurred) {
720 valP->_type = XMLRPC_TYPE_STRING;
722 /* Build our wchar_t block first. */
724 XMLRPC_MEMBLOCK_NEW(wchar_t, envP, length + 1);
725 if (!envP->fault_occurred) {
726 wchar_t * const wcs_contents =
727 XMLRPC_MEMBLOCK_CONTENTS(wchar_t, valP->_wcs_block);
729 xmlrpc_mem_block * utf8P;
731 memcpy(wcs_contents, value, length * sizeof(wchar_t));
732 wcs_contents[length] = '\0';
734 /* Convert the wcs block to UTF-8. */
735 utf8P = xmlrpc_wcs_to_utf8(envP, wcs_contents, length + 1);
736 if (!envP->fault_occurred) {
737 char * const utf8_contents =
738 XMLRPC_MEMBLOCK_CONTENTS(char, utf8P);
739 size_t const utf8_len = XMLRPC_MEMBLOCK_SIZE(char, utf8P);
741 /* XXX - We need an extra memcopy to initialize _block. */
742 XMLRPC_MEMBLOCK_INIT(char, envP, &valP->_block, utf8_len);
743 if (!envP->fault_occurred) {
745 contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valP->_block);
746 memcpy(contents, utf8_contents, utf8_len);
748 XMLRPC_MEMBLOCK_FREE(char, utf8P);
750 if (envP->fault_occurred)
751 XMLRPC_MEMBLOCK_FREE(wchar_t, valP->_wcs_block);
753 if (envP->fault_occurred)
762 xmlrpc_string_w_new(xmlrpc_env * const envP,
763 const wchar_t * const value) {
764 return xmlrpc_string_w_new_lp(envP, wcslen(value), value);
769 xmlrpc_base64_new(xmlrpc_env * const envP,
771 const unsigned char * const value) {
775 xmlrpc_createXmlrpcValue(envP, &valP);
777 if (!envP->fault_occurred) {
778 valP->_type = XMLRPC_TYPE_BASE64;
780 xmlrpc_mem_block_init(envP, &valP->_block, length);
781 if (!envP->fault_occurred) {
782 char * const contents =
783 xmlrpc_mem_block_contents(&valP->_block);
784 memcpy(contents, value, length);
786 if (envP->fault_occurred)
794 /* array stuff is in xmlrpc_array.c */
799 xmlrpc_cptr_new(xmlrpc_env * const envP,
800 void * const value) {
804 xmlrpc_createXmlrpcValue(envP, &valP);
806 if (!envP->fault_occurred) {
807 valP->_type = XMLRPC_TYPE_C_PTR;
808 valP->_value.c_ptr = value;
816 xmlrpc_nil_new(xmlrpc_env * const envP) {
819 xmlrpc_createXmlrpcValue(envP, &valP);
820 if (!envP->fault_occurred)
821 valP->_type = XMLRPC_TYPE_NIL;
828 /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
829 ** Copyright (C) 2001 by Eric Kidd. All rights reserved.
831 ** Redistribution and use in source and binary forms, with or without
832 ** modification, are permitted provided that the following conditions
834 ** 1. Redistributions of source code must retain the above copyright
835 ** notice, this list of conditions and the following disclaimer.
836 ** 2. Redistributions in binary form must reproduce the above copyright
837 ** notice, this list of conditions and the following disclaimer in the
838 ** documentation and/or other materials provided with the distribution.
839 ** 3. The name of the author may not be used to endorse or promote products
840 ** derived from this software without specific prior written permission.
842 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
843 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
844 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
845 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
846 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
847 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
848 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
849 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
850 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
851 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF