2 This file is part of libXMLRPC - a C library for xml-encoded function calls.
4 Author: Dan Libby (dan@libby.com)
5 Epinions.com may be contacted at feedback@epinions-inc.com
9 Copyright 2000 Epinions, Inc.
11 Subject to the following 3 conditions, Epinions, Inc. permits you, free
12 of charge, to (a) use, copy, distribute, modify, perform and display this
13 software and associated documentation files (the "Software"), and (b)
14 permit others to whom the Software is furnished to do so as well.
16 1) The above copyright notice and this permission notice shall be included
17 without modification in all copies or substantial portions of the
20 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF
21 ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY
22 IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 PURPOSE OR NONINFRINGEMENT.
25 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
26 SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
27 OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
28 NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
34 static const char rcsid[] = "#(@) $Id$";
41 * Dan Libby, aka danda (dan@libby.com)
46 * Revision 1.6 2004/04/27 17:33:59 iliaa
47 * Removed C++ style comments.
49 * Revision 1.5 2003/12/16 21:00:21 sniper
50 * Fix some compile warnings (patch by Joe Orton)
52 * Revision 1.4 2002/07/05 04:43:53 danda
53 * merged in updates from SF project. bring php repository up to date with xmlrpc-epi version 0.51
55 * Revision 1.22 2002/03/09 23:15:44 danda
56 * add fault interrogation funcs
58 * Revision 1.21 2002/03/09 22:27:41 danda
59 * win32 build patches contributed by Jeff Lawson
61 * Revision 1.20 2002/02/13 20:58:50 danda
62 * patch to make source more windows friendly, contributed by Jeff Lawson
64 * Revision 1.19 2001/10/12 23:25:54 danda
65 * default to writing xmlrpc
67 * Revision 1.18 2001/09/29 21:58:05 danda
68 * adding cvs log to history section
70 * 10/15/2000 -- danda -- adding robodoc documentation
71 * 08/2000 -- danda -- PHP C extension that uses XMLRPC
72 * 08/2000 -- danda -- support for two vocabularies: danda-rpc and xml-rpc
73 * 09/1999 -- danda -- Initial API, before I even knew of standard XMLRPC vocab. Response only.
74 * 07/2000 -- danda -- wrote new implementation to be compatible with xmlrpc standard and
75 * incorporated some ideas from ensor, most notably the separation of
76 * xml dom from xmlrpc api.
77 * 06/2000 -- danda -- played with expat-ensor from www.ensor.org. Cool, but some flaws.
80 * Coded on RedHat Linux 6.2. Builds on Solaris x86. Should build on just
81 * about anything with minor mods.
83 * Welcome to XMLRPC. For more info on the specification and history, see
84 * http://www.xmlrpc.org.
86 * This code aims to be a full-featured C implementation of XMLRPC. It does not
87 * have any networking code. Rather, it is intended to be plugged into apps
88 * or libraries with existing networking facilities, eg PHP, apache, perl, mozilla,
89 * home-brew application servers, etc.
92 * The user of this library will typically be implementing either an XMLRPC server,
93 * an XMLRPC client, or both. The client will use the library to build an in-memory
94 * representation of a request, and then serialize (encode) that request into XML. The
95 * client will then send the XML to the server via external mechanism. The server will
96 * de-serialize the XML back into an binary representation, call the appropriate registered
97 * method -- thereby generating a response. The response will be serialized into XML and
98 * sent back to the client. The client will de-serialize it into memory, and can
99 * iterate through the results via API.
101 * Both the request and the response may consist of arbitrarily long, arbitrarily nested
102 * values. The values may be one of several types, as defined by XMLRPC_VALUE_TYPE.
104 * Features and Architecture:
105 * - The XML parsing (xml_element.c) is completely independent of the XMLRPC api. In fact,
106 * it can be used as a standalone dom implementation.
107 * - Because of this, the same XMLRPC data can be serialized into multiple xml vocabularies.
108 * It is simply a matter of writing a transport. So far, two transports have been defined.
109 * The default xmlrpc vocab (xml_to_xmlrpc.c), and simple-rpc (xml_to_dandarpc.c) which is
110 * proprietary, but imho more readable, and nice for proprietary legacy reasons.
111 * - Various output options, including: xml escaping via CDATA or entity, case folding,
112 * vocab version, and character encoding.
113 * - One to One mapping between C structures and actual values, unlike ensor which forces
114 * one to understand the arcana of the xmlrpc vocab.
115 * - support for mixed indexed/keyed vector types, making it more compatible with
116 * languages such as PHP.
117 * - quite speedy compared to implementations written in interpreted languages. Also, uses
118 * intelligent string handling, so not many strlen() calls, etc.
119 * - comprehensive API for manipulation of values
124 #include "xmlrpc_win32.h"
138 #include "xml_to_xmlrpc.h"
139 #include "xml_to_dandarpc.h"
140 #include "xml_to_soap.h"
141 #include "xml_element.h"
142 #include "xmlrpc_private.h"
143 #include "xmlrpc_introspection_private.h"
144 #include "system_methods_private.h"
148 /*-*********************
149 * Begin Time Functions *
150 ***********************/
152 static int date_from_ISO8601 (const char *text, time_t * value) {
158 if (strchr (text, '-')) {
159 char *p = (char *) text, *p2 = buf;
173 if(strlen(text) < 17) {
179 for(i = 0; i < 4; i++) {
180 tm.tm_year += (text[i]-'0')*n;
185 for(i = 0; i < 2; i++) {
186 tm.tm_mon += (text[i+4]-'0')*n;
193 for(i = 0; i < 2; i++) {
194 tm.tm_mday += (text[i+6]-'0')*n;
200 for(i = 0; i < 2; i++) {
201 tm.tm_hour += (text[i+9]-'0')*n;
207 for(i = 0; i < 2; i++) {
208 tm.tm_min += (text[i+12]-'0')*n;
214 for(i = 0; i < 2; i++) {
215 tm.tm_sec += (text[i+15]-'0')*n;
221 *value = mktime(&tm);
227 static int date_to_ISO8601 (time_t value, char *buf, int length) {
229 tm = localtime(&value);
230 #if 0 /* TODO: soap seems to favor this method. xmlrpc the latter. */
231 return strftime (buf, length, "%Y-%m-%dT%H:%M:%SZ", tm);
233 return strftime(buf, length, "%Y%m%dT%H:%M:%S", tm);
237 /*-*******************
238 * End Time Functions *
239 *********************/
242 /*-***************************
243 * Begin XMLRPC_REQUEST funcs *
244 *****************************/
246 /****f* REQUEST/XMLRPC_RequestNew
250 * XMLRPC_REQUEST XMLRPC_RequestNew()
252 * Creates a new XMLRPC_Request data struct
256 * XMLRPC_RequestFree ()
259 XMLRPC_REQUEST XMLRPC_RequestNew() {
260 XMLRPC_REQUEST xRequest = calloc(1, sizeof(STRUCT_XMLRPC_REQUEST));
262 simplestring_init(&xRequest->methodName);
269 /****f* REQUEST/XMLRPC_RequestFree
273 * void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO)
275 * Free XMLRPC Request and all sub-values
277 * request -- previously allocated request struct
278 * bFreeIO -- 1 = also free request value data, if any, 0 = ignore.
280 * XMLRPC_RequestNew ()
281 * XMLRPC_CleanupValue ()
284 void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO) {
286 simplestring_free(&request->methodName);
288 if(request->io && bFreeIO) {
289 XMLRPC_CleanupValue(request->io);
292 XMLRPC_CleanupValue(request->error);
300 /* Set Method Name to call */
301 /****f* REQUEST/XMLRPC_RequestSetMethodName
303 * XMLRPC_RequestSetMethodName
305 * const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName)
307 * Set name of method to call with this request.
309 * request -- previously allocated request struct
310 * methodName -- name of method
312 * XMLRPC_RequestNew ()
313 * XMLRPC_RequestGetMethodName ()
314 * XMLRPC_RequestFree ()
317 const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName) {
319 simplestring_clear(&request->methodName);
320 simplestring_add(&request->methodName, methodName);
321 return request->methodName.str;
328 /****f* REQUEST/XMLRPC_RequestGetMethodName
330 * XMLRPC_RequestGetMethodName
332 * const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request)
334 * Get name of method called by this request
336 * request -- previously allocated request struct
338 * XMLRPC_RequestNew ()
339 * XMLRPC_RequestSetMethodName ()
340 * XMLRPC_RequestFree ()
343 const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request) {
344 return request ? request->methodName.str : NULL;
349 /****f* REQUEST/XMLRPC_RequestSetRequestType
351 * XMLRPC_RequestSetRequestType
353 * XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType(XMLRPC_REQUEST request, XMLRPC_REQUEST_TYPE type)
355 * A request struct may be allocated by a caller or by xmlrpc
356 * in response to a request. This allows setting the
359 * request -- previously allocated request struct
360 * type -- request type [xmlrpc_method_call | xmlrpc_method_response]
362 * XMLRPC_RequestNew ()
363 * XMLRPC_RequestGetRequestType ()
364 * XMLRPC_RequestFree ()
365 * XMLRPC_REQUEST_TYPE
368 XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType (XMLRPC_REQUEST request,
369 XMLRPC_REQUEST_TYPE type) {
371 request->request_type = type;
372 return request->request_type;
374 return xmlrpc_request_none;
379 /****f* REQUEST/XMLRPC_RequestGetRequestType
381 * XMLRPC_RequestGetRequestType
383 * XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request)
385 * A request struct may be allocated by a caller or by xmlrpc
386 * in response to a request. This allows setting the
389 * request -- previously allocated request struct
391 * type -- request type [xmlrpc_method_call | xmlrpc_method_response]
393 * XMLRPC_RequestNew ()
394 * XMLRPC_RequestSetRequestType ()
395 * XMLRPC_RequestFree ()
396 * XMLRPC_REQUEST_TYPE
399 XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request) {
400 return request ? request->request_type : xmlrpc_request_none;
406 /****f* REQUEST/XMLRPC_RequestSetData
408 * XMLRPC_RequestSetData
410 * XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data)
412 * Associates a block of xmlrpc data with the request. The
413 * data is *not* copied. A pointer is kept. The caller
414 * should be careful not to doubly free the data value,
415 * which may optionally be free'd by XMLRPC_RequestFree().
417 * request -- previously allocated request struct
418 * data -- previously allocated data struct
420 * XMLRPC_VALUE -- pointer to value stored, or NULL
422 * XMLRPC_RequestNew ()
423 * XMLRPC_RequestGetData ()
424 * XMLRPC_RequestFree ()
429 XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data) {
430 if(request && data) {
432 XMLRPC_CleanupValue (request->io);
434 request->io = XMLRPC_CopyValue(data);
442 /****f* REQUEST/XMLRPC_RequestGetData
444 * XMLRPC_RequestGetData
446 * XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request)
448 * Returns data associated with request, if any.
450 * request -- previously allocated request struct
452 * XMLRPC_VALUE -- pointer to value stored, or NULL
454 * XMLRPC_RequestNew ()
455 * XMLRPC_RequestSetData ()
456 * XMLRPC_RequestFree ()
461 XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request) {
462 return request ? request->io : NULL;
467 /****f* REQUEST/XMLRPC_RequestSetError
469 * XMLRPC_RequestSetError
471 * XMLRPC_VALUE XMLRPC_RequestSetError(XMLRPC_REQUEST request, XMLRPC_VALUE error)
473 * Associates a block of xmlrpc data, representing an error
474 * condition, with the request.
476 * request -- previously allocated request struct
477 * error -- previously allocated error code or struct
479 * XMLRPC_VALUE -- pointer to value stored, or NULL
481 * This is a private function for usage by internals only.
483 * XMLRPC_RequestGetError ()
486 XMLRPC_VALUE XMLRPC_RequestSetError (XMLRPC_REQUEST request, XMLRPC_VALUE error) {
487 if (request && error) {
488 if (request->error) {
489 XMLRPC_CleanupValue (request->error);
491 request->error = XMLRPC_CopyValue (error);
492 return request->error;
499 /****f* REQUEST/XMLRPC_RequestGetError
501 * XMLRPC_RequestGetError
503 * XMLRPC_VALUE XMLRPC_RequestGetError(XMLRPC_REQUEST request)
505 * Returns error data associated with request, if any.
507 * request -- previously allocated request struct
509 * XMLRPC_VALUE -- pointer to error value stored, or NULL
511 * This is a private function for usage by internals only.
513 * XMLRPC_RequestSetError ()
514 * XMLRPC_RequestFree ()
517 XMLRPC_VALUE XMLRPC_RequestGetError (XMLRPC_REQUEST request) {
518 return request ? request->error : NULL;
524 /****f* REQUEST/XMLRPC_RequestSetOutputOptions
526 * XMLRPC_RequestSetOutputOptions
528 * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output)
530 * Sets output options used for generating XML. The output struct
531 * is copied, and may be freed by the caller.
533 * request -- previously allocated request struct
534 * output -- output options struct initialized by caller
536 * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to value stored, or NULL
538 * XMLRPC_RequestNew ()
539 * XMLRPC_RequestGetOutputOptions ()
540 * XMLRPC_RequestFree ()
542 * XMLRPC_REQUEST_OUTPUT_OPTIONS
545 XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output) {
546 if(request && output) {
547 memcpy (&request->output, output,
548 sizeof (STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS));
549 return &request->output;
557 /****f* REQUEST/XMLRPC_RequestGetOutputOptions
559 * XMLRPC_RequestGetOutputOptions
561 * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request)
563 * Gets a pointer to output options used for generating XML.
565 * request -- previously allocated request struct
567 * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to options stored, or NULL
569 * XMLRPC_RequestNew ()
570 * XMLRPC_RequestSetOutputOptions ()
571 * XMLRPC_RequestFree ()
573 * XMLRPC_REQUEST_OUTPUT_OPTIONS
576 XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request) {
577 return request ? &request->output : NULL;
582 /*-*************************
583 * End XMLRPC_REQUEST funcs *
584 ***************************/
587 /*-***************************
588 * Begin Serializiation funcs *
589 *****************************/
591 /****f* SERIALIZE/XMLRPC_VALUE_ToXML
595 * char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val)
597 * encode XMLRPC_VALUE into XML buffer. Note that the generated
598 * buffer will not contain a methodCall.
600 * val -- previously allocated XMLRPC_VALUE
601 * buf_len -- length of returned buffer, if not null
603 * char* -- newly allocated buffer containing XML.
604 * It is the caller's responsibility to free it.
606 * XMLRPC_REQUEST_ToXML ()
607 * XMLRPC_VALUE_FromXML ()
612 char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val, int* buf_len) {
613 xml_element *root_elem = XMLRPC_VALUE_to_xml_element(val);
617 pRet = xml_elem_serialize_to_string(root_elem, NULL, buf_len);
618 xml_elem_free(root_elem);
625 /****f* SERIALIZE/XMLRPC_REQUEST_ToXML
627 * XMLRPC_REQUEST_ToXML
629 * char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request)
631 * encode XMLRPC_REQUEST into XML buffer
633 * request -- previously allocated XMLRPC_REQUEST
634 * buf_len -- size of returned buf, if not null
636 * char* -- newly allocated buffer containing XML.
637 * It is the caller's responsibility to free it.
639 * XMLRPC_REQUEST_ToXML ()
640 * XMLRPC_REQUEST_FromXML ()
642 * XMLRPC_VALUE_ToXML ()
646 char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request, int* buf_len) {
649 xml_element *root_elem = NULL;
650 if (request->output.version == xmlrpc_version_simple) {
651 root_elem = DANDARPC_REQUEST_to_xml_element (request);
653 else if (request->output.version == xmlrpc_version_1_0 ||
654 request->output.version == xmlrpc_version_none) {
655 root_elem = XMLRPC_REQUEST_to_xml_element (request);
657 else if (request->output.version == xmlrpc_version_soap_1_1) {
658 root_elem = SOAP_REQUEST_to_xml_element (request);
663 xml_elem_serialize_to_string (root_elem,
664 &request->output.xml_elem_opts,
666 xml_elem_free(root_elem);
674 /****f* SERIALIZE/XMLRPC_VALUE_FromXML
676 * XMLRPC_VALUE_FromXML
678 * XMLRPC_VALUE XMLRPC_VALUE_FromXML(const char* in_buf, int le
680 * Retrieve XMLRPC_VALUE from XML buffer. Note that this will
681 * ignore any methodCall. See XMLRPC_REQUEST_FromXML
683 * in_buf -- character buffer containing XML
684 * len -- length of buffer
686 * XMLRPC_VALUE -- newly allocated data, or NULL if error. Should
687 * be free'd by caller.
689 * XMLRPC_VALUE_ToXML ()
690 * XMLRPC_REQUEST_FromXML ()
694 XMLRPC_VALUE XMLRPC_VALUE_FromXML (const char *in_buf, int len, XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
695 XMLRPC_VALUE xResponse = NULL;
696 XMLRPC_REQUEST req = XMLRPC_REQUEST_FromXML(in_buf, len, in_options);
700 XMLRPC_RequestFree(req, 0);
707 /* map parser errors to standard xml-rpc errors */
708 static XMLRPC_VALUE map_expat_errors(XML_ELEM_ERROR error) {
709 XMLRPC_VALUE xReturn = NULL;
711 XMLRPC_ERROR_CODE code;
713 snprintf(buf, sizeof(buf),
714 "error occurred at line %ld, column %ld, byte index %ld",
715 error->line, error->column, error->byte_index);
717 /* expat specific errors */
718 switch(error->parser_code) {
719 case XML_ERROR_UNKNOWN_ENCODING:
720 code = xmlrpc_error_parse_unknown_encoding;
722 case XML_ERROR_INCORRECT_ENCODING:
723 code = xmlrpc_error_parse_bad_encoding;
726 code = xmlrpc_error_parse_xml_syntax;
729 xReturn = XMLRPC_UtilityCreateFault(code, buf);
734 /****f* SERIALIZE/XMLRPC_REQUEST_FromXML
736 * XMLRPC_REQUEST_FromXML
738 * XMLRPC_REQUEST XMLRPC_REQUEST_FromXML(const char* in_buf, int le
740 * Retrieve XMLRPC_REQUEST from XML buffer
742 * in_buf -- character buffer containing XML
743 * len -- length of buffer
745 * XMLRPC_REQUEST -- newly allocated data, or NULL if error. Should
746 * be free'd by caller.
748 * XMLRPC_REQUEST_ToXML ()
749 * XMLRPC_VALUE_FromXML ()
753 XMLRPC_REQUEST XMLRPC_REQUEST_FromXML (const char *in_buf, int len,
754 XMLRPC_REQUEST_INPUT_OPTIONS in_options) {
755 XMLRPC_REQUEST request = XMLRPC_RequestNew();
756 STRUCT_XML_ELEM_ERROR error = {0};
759 xml_element *root_elem =
760 xml_elem_parse_buf (in_buf, len,
761 (in_options ? &in_options->xml_elem_opts : NULL),
765 if(!strcmp(root_elem->name, "simpleRPC")) {
766 request->output.version = xmlrpc_version_simple;
767 xml_element_to_DANDARPC_REQUEST(request, root_elem);
769 else if (!strcmp (root_elem->name, "SOAP-ENV:Envelope")) {
770 request->output.version = xmlrpc_version_soap_1_1;
771 xml_element_to_SOAP_REQUEST (request, root_elem);
774 request->output.version = xmlrpc_version_1_0;
775 xml_element_to_XMLRPC_REQUEST(request, root_elem);
777 xml_elem_free(root_elem);
780 if(error.parser_error) {
781 XMLRPC_RequestSetError (request, map_expat_errors (&error));
791 /*-************************
792 * End Serialization Funcs *
793 **************************/
797 /****f* VALUE/XMLRPC_CreateValueEmpty
799 * XMLRPC_CreateValueEmpty
801 * XMLRPC_VALUE XMLRPC_CreateValueEmpty ()
803 * Create an XML value to be used/modified elsewhere.
806 * XMLRPC_VALUE. The new value, or NULL on failure.
808 * XMLRPC_CleanupValue ()
812 XMLRPC_VALUE XMLRPC_CreateValueEmpty() {
813 XMLRPC_VALUE v = calloc(1, sizeof(STRUCT_XMLRPC_VALUE));
815 #ifdef XMLRPC_DEBUG_REFCOUNT
816 printf ("calloc'd 0x%x\n", v);
818 v->type = xmlrpc_empty;
819 simplestring_init(&v->id);
820 simplestring_init(&v->str);
827 /****f* VALUE/XMLRPC_SetValueID_Case
829 * XMLRPC_SetValueID_Case
831 * const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case)
833 * Assign an ID (key) to an XMLRPC value.
835 * value The xml value who's ID we will set.
836 * id The desired new id.
837 * len length of id string if known, or 0 if unknown.
838 * id_case one of XMLRPC_CASE
840 * const char* pointer to the newly allocated id string, or NULL
842 * XMLRPC_SetValueID ()
843 * XMLRPC_GetValueID ()
848 const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case) {
849 const char* pRetval = NULL;
852 simplestring_clear(&value->id);
853 (len > 0) ? simplestring_addn(&value->id, id, len) :
854 simplestring_add(&value->id, id);
856 /* upper or lower case string in place if required. could be a seperate func. */
857 if(id_case == xmlrpc_case_lower || id_case == xmlrpc_case_upper) {
859 for(i = 0; i < value->id.len; i++) {
862 xmlrpc_case_lower) ? tolower (value->id.
863 str[i]) : toupper (value->
869 pRetval = value->id.str;
871 #ifdef XMLRPC_DEBUG_REFCOUNT
872 printf("set value id: %s\n", pRetval);
883 /****f* VALUE/XMLRPC_SetValueString
885 * XMLRPC_SetValueString
887 * const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len)
889 * Assign a string value to an XMLRPC_VALUE, and set it to type xmlrpc_string
891 * value The xml value who's ID we will set.
892 * val The desired new string val.
893 * len length of val string if known, or 0 if unknown.
895 * const char* pointer to the newly allocated value string, or NULL
897 * XMLRPC_GetValueString ()
902 const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len) {
903 char *pRetval = NULL;
905 simplestring_clear(&value->str);
906 (len > 0) ? simplestring_addn(&value->str, val, len) :
907 simplestring_add(&value->str, val);
908 value->type = xmlrpc_string;
909 pRetval = (char *)value->str.str;
917 /****f* VALUE/XMLRPC_SetValueInt
921 * void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val)
923 * Assign an int value to an XMLRPC_VALUE, and set it to type xmlrpc_int
925 * value The xml value who's ID we will set.
926 * val The desired new integer value
929 * XMLRPC_GetValueInt ()
934 void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val) {
936 value->type = xmlrpc_int;
943 /****f* VALUE/XMLRPC_SetValueBoolean
945 * XMLRPC_SetValueBoolean
947 * void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val)
949 * Assign a boolean value to an XMLRPC_VALUE, and set it to type xmlrpc_boolean
951 * value The xml value who's value we will set.
952 * val The desired new boolean value. [0 | 1]
955 * XMLRPC_GetValueBoolean ()
960 void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val) {
962 value->type = xmlrpc_boolean;
963 value->i = val ? 1 : 0;
970 /****f* VECTOR/XMLRPC_SetIsVector
974 * int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type)
976 * Set the XMLRPC_VALUE to be a vector (list) type. The vector may be one of
977 * [xmlrpc_array | xmlrpc_struct | xmlrpc_mixed]. An array has only index values.
978 * A struct has key/val pairs. Mixed allows both index and key/val combinations.
980 * value The xml value who's vector type we will set
981 * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE
983 * int 1 if successful, 0 otherwise
985 * XMLRPC_GetValueType ()
986 * XMLRPC_GetVectorType ()
992 int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type) {
996 /* we can change the type so long as nothing is currently stored. */
997 if(value->type == xmlrpc_vector) {
999 if(!Q_Size(value->v->q)) {
1000 value->v->type = type;
1005 value->v = calloc(1, sizeof(STRUCT_XMLRPC_VECTOR));
1007 value->v->q = (queue*)malloc(sizeof(queue));
1009 Q_Init(value->v->q);
1010 value->v->type = type;
1011 value->type = xmlrpc_vector;
1023 /****f* VECTOR/XMLRPC_CreateVector
1025 * XMLRPC_CreateVector
1027 * XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type)
1029 * Create a new vector and optionally set an id.
1031 * id The id of the vector, or NULL
1032 * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE
1034 * XMLRPC_VALUE The new vector, or NULL on failure.
1036 * XMLRPC_CreateValueEmpty ()
1037 * XMLRPC_SetIsVector ()
1038 * XMLRPC_GetValueType ()
1039 * XMLRPC_GetVectorType ()
1041 * XMLRPC_VECTOR_TYPE
1045 XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type) {
1046 XMLRPC_VALUE val = NULL;
1048 val = XMLRPC_CreateValueEmpty();
1050 if(XMLRPC_SetIsVector(val, type)) {
1052 const char *pSVI = NULL;
1054 pSVI = XMLRPC_SetValueID(val, id, 0);
1070 /* Not yet implemented.
1072 * This should use a hash to determine if a given target id has already
1075 * Alternately, it could walk the entire vector, but that could be quite
1076 * slow for very large lists.
1078 static int isDuplicateEntry(XMLRPC_VALUE target, XMLRPC_VALUE source) {
1082 /****f* VECTOR/XMLRPC_AddValueToVector
1084 * XMLRPC_AddValueToVector
1086 * int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source)
1088 * Add (append) an existing XMLRPC_VALUE to a vector.
1090 * target The target vector
1091 * source The source value to append
1093 * int 1 if successful, else 0
1095 * XMLRPC_AddValuesToVector ()
1096 * XMLRPC_VectorGetValueWithID_Case ()
1099 * The function will fail and return 0 if an attempt is made to add
1100 * a value with an ID into a vector of type xmlrpc_vector_array. Such
1101 * values can only be added to xmlrpc_vector_struct.
1104 int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source) {
1105 if(target && source) {
1106 if(target->type == xmlrpc_vector && target->v &&
1107 target->v->q && target->v->type != xmlrpc_vector_none) {
1109 /* guard against putting value of unknown type into vector */
1110 switch(source->type) {
1114 case xmlrpc_boolean:
1115 case xmlrpc_datetime:
1120 /* Guard against putting a key/val pair into an array vector */
1121 if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) {
1122 if (isDuplicateEntry (target, source)
1123 || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) {
1129 "xmlrpc: attempted to add key/val pair to vector of type array\n");
1134 "xmlrpc: attempted to add value of unknown type to vector\n");
1145 /****f* VECTOR/XMLRPC_AddValuesToVector
1147 * XMLRPC_AddValuesToVector
1149 * XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 )
1150 * XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... )
1152 * Add (append) a series of existing XMLRPC_VALUE to a vector.
1154 * target The target vector
1155 * ... The source value(s) to append. The last item *must* be 0.
1157 * int 1 if successful, else 0
1159 * XMLRPC_AddValuesToVector ()
1160 * XMLRPC_VectorGetValueWithID_Case ()
1163 * This function may actually return failure after it has already modified
1164 * or added items to target. You can not trust the state of target
1165 * if this function returns failure.
1168 int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) {
1172 if(target->type == xmlrpc_vector) {
1173 XMLRPC_VALUE v = NULL;
1176 va_start(vl, target);
1179 v = va_arg(vl, XMLRPC_VALUE);
1181 if(!XMLRPC_AddValueToVector(target, v)) {
1202 /****f* VECTOR/XMLRPC_VectorGetValueWithID_Case
1204 * XMLRPC_VectorGetValueWithID_Case
1206 * XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case)
1208 * Get value from vector matching id (key)
1210 * vector The source vector
1211 * id The key to find
1212 * id_case Rule for how to match key
1214 * int 1 if successful, else 0
1216 * XMLRPC_SetValueID_Case ()
1218 * XMLRPC_CASE_COMPARISON
1221 XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id,
1222 XMLRPC_CASE_COMPARISON id_case) {
1223 if(vector && vector->v && vector->v->q) {
1224 q_iter qi = Q_Iter_Head_F(vector->v->q);
1227 XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1228 if(xIter && xIter->id.str) {
1229 if(id_case == xmlrpc_case_sensitive) {
1230 if(!strcmp(xIter->id.str, id)) {
1234 else if(id_case == xmlrpc_case_insensitive) {
1235 if(!strcasecmp(xIter->id.str, id)) {
1240 qi = Q_Iter_Next_F(qi);
1249 int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) {
1250 if(vector && vector->v && vector->v->q && value) {
1251 q_iter qi = Q_Iter_Head_F(vector->v->q);
1254 XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1255 if(xIter == value) {
1256 XMLRPC_CleanupValue(xIter);
1257 Q_Iter_Del(vector->v->q, qi);
1260 qi = Q_Iter_Next_F(qi);
1267 /****f* VALUE/XMLRPC_CreateValueString
1269 * XMLRPC_CreateValueString
1271 * XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len)
1273 * Create an XMLRPC_VALUE, and assign a string to it
1275 * id The id of the value, or NULL
1276 * val The desired new string val.
1277 * len length of val string if known, or 0 if unknown.
1279 * newly allocated XMLRPC_VALUE, or NULL
1281 * XMLRPC_GetValueString ()
1282 * XMLRPC_CreateValueEmpty ()
1287 XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) {
1288 XMLRPC_VALUE value = NULL;
1290 value = XMLRPC_CreateValueEmpty();
1292 XMLRPC_SetValueString(value, val, len);
1294 XMLRPC_SetValueID(value, id, 0);
1303 /****f* VALUE/XMLRPC_CreateValueInt
1305 * XMLRPC_CreateValueInt
1307 * XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i)
1309 * Create an XMLRPC_VALUE, and assign an int to it
1311 * id The id of the value, or NULL
1312 * i The desired new int val.
1314 * newly allocated XMLRPC_VALUE, or NULL
1316 * XMLRPC_GetValueInt ()
1317 * XMLRPC_CreateValueEmpty ()
1322 XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) {
1323 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1325 XMLRPC_SetValueInt(val, i);
1327 XMLRPC_SetValueID(val, id, 0);
1335 /****f* VALUE/XMLRPC_CreateValueBoolean
1337 * XMLRPC_CreateValueBoolean
1339 * XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i)
1341 * Create an XMLRPC_VALUE, and assign an int to it
1343 * id The id of the value, or NULL
1344 * i The desired new int val.
1346 * newly allocated XMLRPC_VALUE, or NULL
1348 * XMLRPC_GetValueBoolean ()
1349 * XMLRPC_CreateValueEmpty ()
1354 XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) {
1355 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1357 XMLRPC_SetValueBoolean(val, i);
1359 XMLRPC_SetValueID(val, id, 0);
1368 /****f* VALUE/XMLRPC_CleanupValue
1370 * XMLRPC_CleanupValue
1372 * void XMLRPC_CleanupValue(XMLRPC_VALUE value)
1374 * Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector)
1376 * value The id of the value to be cleaned up.
1380 * Normally this function will be called for the topmost vector, thus free-ing
1381 * all children. If a child of a vector is free'd first, results are undefined.
1382 * Failure to call this function *will* cause memory leaks.
1384 * Also, this function is implemented using reference counting. Thus a value
1385 * may be added and freed from multiple parents so long as a reference is added
1386 * first using XMLRPC_CopyValue()
1388 * XMLRPC_RequestFree ()
1389 * XMLRPC_CreateValueEmpty ()
1390 * XMLRPC_CopyValue()
1394 void XMLRPC_CleanupValue(XMLRPC_VALUE value) {
1396 if(value->iRefCount > 0) {
1397 value->iRefCount --;
1400 #ifdef XMLRPC_DEBUG_REFCOUNT
1402 printf ("decremented refcount of %s, now %i\n", value->id.str,
1406 printf ("decremented refcount of 0x%x, now %i\n", value,
1411 if(value->type == xmlrpc_vector) {
1413 if(value->iRefCount == 0) {
1414 XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q);
1416 XMLRPC_CleanupValue(cur);
1418 /* Make sure some idiot didn't include a vector as a child of itself
1419 * and thus it would have already free'd these.
1421 if(value->v && value->v->q) {
1422 cur = Q_Next(value->v->q);
1429 Q_Destroy(value->v->q);
1430 my_free(value->v->q);
1437 if(value->iRefCount == 0) {
1439 /* guard against freeing invalid types */
1440 switch(value->type) {
1443 case xmlrpc_boolean:
1444 case xmlrpc_datetime:
1449 #ifdef XMLRPC_DEBUG_REFCOUNT
1451 printf("free'd %s\n", value->id.str);
1454 printf("free'd 0x%x\n", value);
1457 simplestring_free(&value->id);
1458 simplestring_free(&value->str);
1460 memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE));
1465 "xmlrpc: attempted to free value of invalid type\n");
1475 /****f* VALUE/XMLRPC_SetValueDateTime
1477 * XMLRPC_SetValueDateTime
1479 * void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time)
1481 * Assign time value to XMLRPC_VALUE
1483 * value The target XMLRPC_VALUE
1484 * time The desired new unix time value (time_t)
1488 * XMLRPC_GetValueDateTime ()
1489 * XMLRPC_SetValueDateTime_ISO8601 ()
1490 * XMLRPC_CreateValueDateTime ()
1494 void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) {
1497 value->type = xmlrpc_datetime;
1502 date_to_ISO8601(time, timeBuf, sizeof(timeBuf));
1505 simplestring_clear(&value->str);
1506 simplestring_add(&value->str, timeBuf);
1513 /****f* VALUE/XMLRPC_CopyValue
1517 * XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value)
1519 * Make a copy (reference) of an XMLRPC_VALUE
1521 * value The target XMLRPC_VALUE
1523 * XMLRPC_VALUE -- address of the copy
1525 * XMLRPC_CleanupValue ()
1526 * XMLRPC_DupValueNew ()
1528 * This function is implemented via reference counting, so the
1529 * returned value is going to be the same as the passed in value.
1530 * The value must be freed the same number of times it is copied
1531 * or there will be a memory leak.
1534 XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) {
1536 value->iRefCount ++;
1537 #ifdef XMLRPC_DEBUG_REFCOUNT
1539 printf ("incremented refcount of %s, now %i\n", value->id.str,
1543 printf ("incremented refcount of 0x%x, now %i\n", value,
1554 /****f* VALUE/XMLRPC_DupValueNew
1556 * XMLRPC_DupValueNew
1558 * XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value)
1560 * Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem.
1562 * value The source XMLRPC_VALUE to duplicate
1564 * XMLRPC_VALUE -- address of the duplicate value
1566 * XMLRPC_CleanupValue ()
1567 * XMLRPC_CopyValue ()
1569 * Use this when function when you need to modify the contents of
1570 * the copied value seperately from the original.
1572 * this function is recursive, thus the value and all of its children
1573 * (if any) will be duplicated.
1576 XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) {
1577 XMLRPC_VALUE xReturn = NULL;
1579 xReturn = XMLRPC_CreateValueEmpty ();
1580 if (xSource->id.len) {
1581 XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len);
1584 switch (xSource->type) {
1586 case xmlrpc_boolean:
1587 XMLRPC_SetValueInt (xReturn, xSource->i);
1591 XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len);
1593 case xmlrpc_datetime:
1594 XMLRPC_SetValueDateTime (xReturn, xSource->i);
1597 XMLRPC_SetValueDouble (xReturn, xSource->d);
1601 q_iter qi = Q_Iter_Head_F (xSource->v->q);
1602 XMLRPC_SetIsVector (xReturn, xSource->v->type);
1605 XMLRPC_VALUE xIter = Q_Iter_Get_F (qi);
1606 XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter));
1607 qi = Q_Iter_Next_F (qi);
1622 /****f* VALUE/XMLRPC_CreateValueDateTime
1624 * XMLRPC_CreateValueDateTime
1626 * XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time)
1628 * Create new datetime value from time_t
1630 * id id of the new value, or NULL
1631 * time The desired unix time value (time_t)
1635 * XMLRPC_GetValueDateTime ()
1636 * XMLRPC_SetValueDateTime ()
1637 * XMLRPC_CreateValueDateTime_ISO8601 ()
1641 XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) {
1642 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1644 XMLRPC_SetValueDateTime(val, time);
1646 XMLRPC_SetValueID(val, id, 0);
1655 /****f* VALUE/XMLRPC_SetValueDateTime_ISO8601
1657 * XMLRPC_SetValueDateTime_ISO8601
1659 * void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s)
1661 * Set datetime value from IS08601 encoded string
1663 * value The target XMLRPC_VALUE
1664 * s The desired new time value
1668 * This function currently attempts to convert the time string to a valid unix time
1669 * value before passing it. Behavior when the string is invalid or out of range
1670 * is not well defined, but will probably result in Jan 1, 1970 (0) being passed.
1672 * XMLRPC_GetValueDateTime_ISO8601 ()
1673 * XMLRPC_CreateValueDateTime_ISO8601 ()
1674 * XMLRPC_CreateValueDateTime ()
1678 void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) {
1680 time_t time_val = 0;
1682 date_from_ISO8601(s, &time_val);
1683 XMLRPC_SetValueDateTime(value, time_val);
1690 /****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601
1692 * XMLRPC_CreateValueDateTime_ISO8601
1694 * XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s)
1696 * Create datetime value from IS08601 encoded string
1698 * id The id of the new value, or NULL
1699 * s The desired new time value
1701 * newly allocated XMLRPC_VALUE, or NULL if no value created.
1703 * See XMLRPC_SetValueDateTime_ISO8601 ()
1705 * XMLRPC_GetValueDateTime_ISO8601 ()
1706 * XMLRPC_SetValueDateTime_ISO8601 ()
1707 * XMLRPC_CreateValueDateTime ()
1711 XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) {
1712 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1714 XMLRPC_SetValueDateTime_ISO8601(val, s);
1716 XMLRPC_SetValueID(val, id, 0);
1725 /****f* VALUE/XMLRPC_SetValueBase64
1727 * XMLRPC_SetValueBase64
1729 * void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len)
1731 * Set base64 value. Base64 is useful for transferring binary data, such as an image.
1733 * value The target XMLRPC_VALUE
1734 * s The desired new binary value
1735 * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1739 * Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and
1740 * decoded on the other side. This is transparent to the caller.
1742 * XMLRPC_GetValueBase64 ()
1743 * XMLRPC_CreateValueBase64 ()
1747 void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) {
1749 simplestring_clear(&value->str);
1750 (len > 0) ? simplestring_addn(&value->str, s, len) :
1751 simplestring_add(&value->str, s);
1752 value->type = xmlrpc_base64;
1759 /****f* VALUE/XMLRPC_CreateValueBase64
1761 * XMLRPC_CreateValueBase64
1763 * XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len)
1765 * Create base64 value. Base64 is useful for transferring binary data, such as an image.
1767 * id id of the new value, or NULL
1768 * s The desired new binary value
1769 * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1771 * newly allocated XMLRPC_VALUE, or NULL if error
1773 * See XMLRPC_SetValueBase64 ()
1775 * XMLRPC_GetValueBase64 ()
1776 * XMLRPC_SetValueBase64 ()
1780 XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) {
1781 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1783 XMLRPC_SetValueBase64(val, s, len);
1785 XMLRPC_SetValueID(val, id, 0);
1793 /****f* VALUE/XMLRPC_SetValueDouble
1795 * XMLRPC_SetValueDouble
1797 * void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val)
1799 * Set double (floating point) value.
1801 * value The target XMLRPC_VALUE
1802 * val The desired new double value
1806 * XMLRPC_GetValueDouble ()
1807 * XMLRPC_CreateValueDouble ()
1811 void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) {
1813 value->type = xmlrpc_double;
1820 /****f* VALUE/XMLRPC_CreateValueDouble
1822 * XMLRPC_CreateValueDouble
1824 * XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d)
1826 * Create double (floating point) value.
1828 * id id of the newly created value, or NULL
1829 * d The desired new double value
1833 * XMLRPC_GetValueDouble ()
1834 * XMLRPC_CreateValueDouble ()
1838 XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) {
1839 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1841 XMLRPC_SetValueDouble(val, d);
1843 XMLRPC_SetValueID(val, id, 0);
1851 /****f* VALUE/XMLRPC_GetValueString
1853 * XMLRPC_GetValueString
1855 * const char* XMLRPC_GetValueString(XMLRPC_VALUE value)
1857 * retrieve string value
1859 * value source XMLRPC_VALUE of type xmlrpc_string
1863 * XMLRPC_SetValueString ()
1864 * XMLRPC_GetValueType ()
1868 const char* XMLRPC_GetValueString(XMLRPC_VALUE value) {
1869 return ((value && value->type == xmlrpc_string) ? value->str.str : 0);
1874 /****f* VALUE/XMLRPC_GetValueStringLen
1876 * XMLRPC_GetValueStringLen
1878 * int XMLRPC_GetValueStringLen(XMLRPC_VALUE value)
1880 * determine length of string value
1882 * value XMLRPC_VALUE of type xmlrpc_string
1884 * length of string, or 0
1887 * XMLRPC_SetValueString ()
1888 * XMLRPC_GetValueString ()
1891 int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) {
1892 return ((value) ? value->str.len : 0);
1897 /****f* VALUE/XMLRPC_GetValueInt
1899 * XMLRPC_GetValueInt
1901 * int XMLRPC_GetValueInt(XMLRPC_VALUE value)
1903 * retrieve integer value.
1905 * value XMLRPC_VALUE of type xmlrpc_int
1907 * integer value or 0 if value is not valid int
1909 * use XMLRPC_GetValueType () to be sure if 0 is real return value or not
1911 * XMLRPC_SetValueInt ()
1912 * XMLRPC_CreateValueInt ()
1915 int XMLRPC_GetValueInt(XMLRPC_VALUE value) {
1916 return ((value && value->type == xmlrpc_int) ? value->i : 0);
1921 /****f* VALUE/XMLRPC_GetValueBoolean
1923 * XMLRPC_GetValueBoolean
1925 * int XMLRPC_GetValueBoolean(XMLRPC_VALUE value)
1927 * retrieve boolean value.
1929 * XMLRPC_VALUE of type xmlrpc_boolean
1931 * boolean value or 0 if value is not valid boolean
1933 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
1935 * XMLRPC_SetValueBoolean ()
1936 * XMLRPC_CreateValueBoolean ()
1939 int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) {
1940 return ((value && value->type == xmlrpc_boolean) ? value->i : 0);
1945 /****f* VALUE/XMLRPC_GetValueDouble
1947 * XMLRPC_GetValueDouble
1949 * double XMLRPC_GetValueDouble(XMLRPC_VALUE value)
1951 * retrieve double value
1953 * XMLRPC_VALUE of type xmlrpc_double
1955 * double value or 0 if value is not valid double.
1957 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
1959 * XMLRPC_SetValueDouble ()
1960 * XMLRPC_CreateValueDouble ()
1963 double XMLRPC_GetValueDouble(XMLRPC_VALUE value) {
1964 return ((value && value->type == xmlrpc_double) ? value->d : 0);
1969 /****f* VALUE/XMLRPC_GetValueBase64
1971 * XMLRPC_GetValueBase64
1973 * const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value)
1975 * retrieve binary value
1977 * XMLRPC_VALUE of type xmlrpc_base64
1979 * pointer to binary value or 0 if value is not valid.
1981 * XMLRPC_SetValueBase64 ()
1982 * XMLRPC_CreateValueBase64 ()
1984 * Call XMLRPC_GetValueStringLen() to retrieve real length of binary data. strlen()
1985 * will not be accurate, as returned data may contain embedded nulls.
1988 const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) {
1989 return ((value && value->type == xmlrpc_base64) ? value->str.str : 0);
1994 /****f* VALUE/XMLRPC_GetValueDateTime
1996 * XMLRPC_GetValueDateTime
1998 * time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value)
2000 * retrieve time_t value
2002 * XMLRPC_VALUE of type xmlrpc_datetime
2004 * time_t value or 0 if value is not valid datetime.
2006 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
2008 * XMLRPC_SetValueDateTime ()
2009 * XMLRPC_GetValueDateTime_ISO8601 ()
2010 * XMLRPC_CreateValueDateTime ()
2013 time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) {
2014 return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0);
2019 /****f* VALUE/XMLRPC_GetValueDateTime_IOS8601
2021 * XMLRPC_GetValueDateTime_IOS8601
2023 * const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value)
2025 * retrieve ISO8601 formatted time value
2027 * XMLRPC_VALUE of type xmlrpc_datetime
2029 * const char* value or 0 if value is not valid datetime.
2031 * XMLRPC_SetValueDateTime_IOS8601 ()
2032 * XMLRPC_GetValueDateTime ()
2033 * XMLRPC_CreateValueDateTime_IOS8601 ()
2036 const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) {
2037 return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0);
2042 /* Get ID (key) of value or NULL */
2043 /****f* VALUE/XMLRPC_GetValueID
2047 * const char* XMLRPC_GetValueID(XMLRPC_VALUE value)
2049 * retrieve id (key) of value
2051 * XMLRPC_VALUE of any type
2053 * const char* pointer to id of value, or NULL
2056 * XMLRPC_SetValueID()
2057 * XMLRPC_CreateValueEmpty()
2060 const char* XMLRPC_GetValueID(XMLRPC_VALUE value) {
2061 return (const char*)((value && value->id.len) ? value->id.str : 0);
2067 /****f* VECTOR/XMLRPC_VectorSize
2071 * int XMLRPC_VectorSize(XMLRPC_VALUE value)
2073 * retrieve size of vector
2075 * XMLRPC_VALUE of type xmlrpc_vector
2077 * count of items in vector
2079 * This is a cheap operation even on large vectors. Vector size is
2080 * maintained by queue during add/remove ops.
2082 * XMLRPC_AddValueToVector ()
2085 int XMLRPC_VectorSize(XMLRPC_VALUE value) {
2087 if(value && value->type == xmlrpc_vector && value->v) {
2088 size = Q_Size(value->v->q);
2095 /****f* VECTOR/XMLRPC_VectorRewind
2097 * XMLRPC_VectorRewind
2099 * XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value)
2101 * reset vector to first item
2103 * XMLRPC_VALUE of type xmlrpc_vector
2105 * first XMLRPC_VALUE in list, or NULL if empty or error.
2107 * Be careful to rewind any vector passed in to you if you expect to
2108 * iterate through the entire list.
2110 * XMLRPC_VectorNext ()
2113 XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) {
2114 XMLRPC_VALUE xReturn = NULL;
2115 if(value && value->type == xmlrpc_vector && value->v) {
2116 xReturn = (XMLRPC_VALUE)Q_Head(value->v->q);
2123 /****f* VECTOR/XMLRPC_VectorNext
2127 * XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value)
2129 * Iterate vector to next item in list.
2131 * XMLRPC_VALUE of type xmlrpc_vector
2133 * Next XMLRPC_VALUE in vector, or NULL if at end.
2136 * XMLRPC_VectorRewind ()
2139 XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) {
2140 XMLRPC_VALUE xReturn = NULL;
2141 if(value && value->type == xmlrpc_vector && value->v) {
2142 xReturn = (XMLRPC_VALUE)Q_Next(value->v->q);
2149 /****f* VALUE/XMLRPC_GetValueType
2151 * XMLRPC_GetValueType
2153 * XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value)
2155 * determine data type of the XMLRPC_VALUE
2157 * XMLRPC_VALUE target of query
2159 * data type of value as enumerated by XMLRPC_VALUE_TYPE
2161 * all values are of type xmlrpc_empty until set.
2162 * Deprecated for public use. See XMLRPC_GetValueTypeEasy
2165 * XMLRPC_CreateValue*
2167 * XMLRPC_GetValueTypeEasy ()
2170 XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) {
2171 return value ? value->type : xmlrpc_empty;
2176 /* Vector type accessor */
2177 /****f* VALUE/XMLRPC_GetVectorType
2179 * XMLRPC_GetVectorType
2181 * XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value)
2183 * determine vector type of the XMLRPC_VALUE
2185 * XMLRPC_VALUE of type xmlrpc_vector
2187 * vector type of value as enumerated by XMLRPC_VECTOR_TYPE.
2188 * xmlrpc_none if not a value.
2190 * xmlrpc_none is returned if value is not a vector
2191 * Deprecated for public use. See XMLRPC_GetValueTypeEasy
2193 * XMLRPC_SetIsVector ()
2194 * XMLRPC_GetValueType ()
2195 * XMLRPC_GetValueTypeEasy ()
2198 XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) {
2199 return(value && value->v) ? value->v->type : xmlrpc_none;
2204 /****f* VALUE/XMLRPC_GetValueTypeEasy
2206 * XMLRPC_GetValueTypeEasy
2208 * XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)
2210 * determine data type of the XMLRPC_VALUE. includes vector types.
2212 * XMLRPC_VALUE target of query
2214 * data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY
2215 * xmlrpc_type_none if not a value.
2217 * all values are of type xmlrpc_type_empty until set.
2220 * XMLRPC_CreateValue*
2224 XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) {
2226 switch (value->type) {
2228 switch (value->v->type) {
2229 case xmlrpc_vector_none:
2230 return xmlrpc_type_none;
2231 case xmlrpc_vector_struct:
2232 return xmlrpc_type_struct;
2233 case xmlrpc_vector_mixed:
2234 return xmlrpc_type_mixed;
2235 case xmlrpc_vector_array:
2236 return xmlrpc_type_array;
2239 /* evil cast, but we know they are the same */
2240 return(XMLRPC_VALUE_TYPE_EASY) value->type;
2250 /*-*******************
2251 * Begin Server Funcs *
2252 *********************/
2255 /****f* VALUE/XMLRPC_ServerCreate
2257 * XMLRPC_ServerCreate
2259 * XMLRPC_SERVER XMLRPC_ServerCreate()
2261 * Allocate/Init XMLRPC Server Resources.
2265 * newly allocated XMLRPC_SERVER
2268 * XMLRPC_ServerDestroy ()
2269 * XMLRPC_GetGlobalServer ()
2272 XMLRPC_SERVER XMLRPC_ServerCreate() {
2273 XMLRPC_SERVER server = calloc(1, sizeof(STRUCT_XMLRPC_SERVER));
2275 Q_Init(&server->methodlist);
2276 Q_Init(&server->docslist);
2278 /* register system methods */
2279 xsm_register(server);
2286 /* Return global server. Not locking! Not Thread Safe! */
2287 /****f* VALUE/XMLRPC_GetGlobalServer
2289 * XMLRPC_GetGlobalServer
2291 * XMLRPC_SERVER XMLRPC_GetGlobalServer()
2293 * Allocates a global (process-wide) server, or returns pointer if pre-existing.
2297 * pointer to global server, or 0 if error.
2299 * ***WARNING*** This function is not thread safe. It is included only for the very lazy.
2300 * Multi-threaded programs that use this may experience problems.
2302 * There is currently no way to cleanup the global server gracefully.
2304 * XMLRPC_ServerCreate ()
2307 XMLRPC_SERVER XMLRPC_GetGlobalServer() {
2308 static XMLRPC_SERVER xsServer = 0;
2310 xsServer = XMLRPC_ServerCreate();
2317 /****f* VALUE/XMLRPC_ServerDestroy
2319 * XMLRPC_ServerDestroy
2321 * void XMLRPC_ServerDestroy(XMLRPC_SERVER server)
2323 * Free Server Resources
2325 * server The server to be free'd
2329 * This frees the server struct and any methods that have been added.
2331 * XMLRPC_ServerCreate ()
2334 void XMLRPC_ServerDestroy(XMLRPC_SERVER server) {
2336 doc_method* dm = Q_Head(&server->docslist);
2337 server_method* sm = Q_Head(&server->methodlist);
2340 dm = Q_Next(&server->docslist);
2347 XMLRPC_CleanupValue(sm->desc);
2350 sm = Q_Next(&server->methodlist);
2352 if(server->xIntrospection) {
2353 XMLRPC_CleanupValue(server->xIntrospection);
2356 Q_Destroy(&server->methodlist);
2357 Q_Destroy(&server->docslist);
2365 /****f* VALUE/XMLRPC_ServerRegisterMethod
2367 * XMLRPC_ServerRegisterMethod
2369 * void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb)
2371 * Register new XMLRPC method with server
2373 * server The XMLRPC_SERVER to register the method with
2374 * name public name of the method
2375 * cb C function that implements the method
2377 * int - 1 if success, else 0
2379 * A C function must be registered for every "method" that the server recognizes. The
2380 * method name is equivalent to <methodCall><name> method name </name></methodCall> in the
2383 * XMLRPC_ServerFindMethod ()
2384 * XMLRPC_ServerCallMethod ()
2387 int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) {
2388 if(server && name && cb) {
2390 server_method* sm = malloc(sizeof(server_method));
2393 sm->name = strdup(name);
2397 return Q_PushTail(&server->methodlist, sm);
2405 server_method* find_method(XMLRPC_SERVER server, const char* name) {
2408 q_iter qi = Q_Iter_Head_F(&server->methodlist);
2411 sm = Q_Iter_Get_F(qi);
2412 if(sm && !strcmp(sm->name, name)) {
2415 qi = Q_Iter_Next_F(qi);
2421 const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) {
2431 case xmlrpc_boolean:
2433 case xmlrpc_datetime:
2443 case xmlrpc_vector_none:
2445 case xmlrpc_vector_array:
2447 case xmlrpc_vector_mixed:
2448 return "mixed vector (struct)";
2449 case xmlrpc_vector_struct:
2456 /****f* VALUE/XMLRPC_ServerFindMethod
2458 * XMLRPC_ServerFindMethod
2460 * XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName)
2462 * retrieve C callback associated with a given method name.
2464 * server The XMLRPC_SERVER the method is registered with
2465 * callName the method to find
2467 * previously registered XMLRPC_Callback, or NULL
2469 * Typically, this is used to determine if a requested method exists, without actually calling it.
2471 * XMLRPC_ServerCallMethod ()
2472 * XMLRPC_ServerRegisterMethod ()
2475 XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) {
2476 if(server && callName) {
2477 q_iter qi = Q_Iter_Head_F(&server->methodlist);
2479 server_method* sm = Q_Iter_Get_F(qi);
2480 if(sm && !strcmp(sm->name, callName)) {
2483 qi = Q_Iter_Next_F(qi);
2492 /* Call method specified in request */
2493 /****f* VALUE/XMLRPC_ServerCallMethod
2495 * XMLRPC_ServerCallMethod
2497 * XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData)
2501 * server The XMLRPC_SERVER the method is registered with
2502 * request the request to handle
2503 * userData any additional data to pass to the C callback, or NULL
2505 * XMLRPC_VALUE allocated by the callback, or NULL
2507 * It is typically the caller's responsibility to free the returned value.
2509 * Often the caller will want to serialize the result as XML, via
2510 * XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML ()
2512 * XMLRPC_ServerFindMethod ()
2513 * XMLRPC_ServerRegisterMethod ()
2514 * XMLRPC_CleanupValue ()
2517 XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) {
2518 XMLRPC_VALUE xReturn = NULL;
2520 /* check for error set during request parsing / generation */
2521 if(request && request->error) {
2522 xReturn = XMLRPC_CopyValue(request->error);
2524 else if (server && request) {
2525 XMLRPC_Callback cb =
2526 XMLRPC_ServerFindMethod (server, request->methodName.str);
2528 xReturn = cb(server, request, userData);
2532 XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method,
2533 request->methodName.str);
2541 /*-*****************
2542 * End server funcs *
2543 *******************/
2546 /*-***********************************
2547 * Begin XMLRPC General Options funcs *
2548 *************************************/
2550 /* For options used by XMLRPC_VALUE funcs that otherwise do not have
2551 * parameters for options. Kind of gross. :(
2553 typedef struct _xmlrpc_options {
2554 XMLRPC_CASE id_case;
2555 XMLRPC_CASE_COMPARISON id_case_compare;
2557 STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS;
2559 static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() {
2560 static STRUCT_XMLRPC_OPTIONS options = {
2562 xmlrpc_case_sensitive
2567 /****f* VALUE/XMLRPC_GetDefaultIdCase
2569 * XMLRPC_GetDefaultIdCase
2571 * XMLRPC_CASE XMLRPC_GetDefaultIdCase()
2573 * Gets default case options used by XMLRPC_VALUE funcs
2579 * Nasty and gross. Should be server specific, but that requires changing all
2580 * the XMLRPC_VALUE api's.
2582 * XMLRPC_SetDefaultIdCase ()
2585 XMLRPC_CASE XMLRPC_GetDefaultIdCase() {
2586 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2587 return options->id_case;
2592 /****f* VALUE/XMLRPC_SetDefaultIdCase
2594 * XMLRPC_SetDefaultIdCase
2596 * XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)
2598 * Sets default case options used by XMLRPC_VALUE funcs
2600 * id_case case options as enumerated by XMLRPC_CASE
2602 * XMLRPC_CASE -- newly set option
2604 * Nasty and gross. Should be server specific, but that requires changing all
2605 * the XMLRPC_VALUE api's.
2607 * XMLRPC_GetDefaultIdCase ()
2610 XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) {
2611 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2612 options->id_case = id_case;
2613 return options->id_case;
2618 /****f* VALUE/XMLRPC_GetDefaultIdCaseComparison
2620 * XMLRPC_GetDefaultIdCaseComparison
2622 * XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( )
2624 * Gets default case comparison options used by XMLRPC_VALUE funcs
2628 * XMLRPC_CASE_COMPARISON default
2630 * Nasty and gross. Should be server specific, but that requires changing all
2631 * the XMLRPC_VALUE api's.
2633 * XMLRPC_SetDefaultIdCaseComparison ()
2636 XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() {
2637 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2638 return options->id_case_compare;
2643 /****f* VALUE/XMLRPC_SetDefaultIdCaseComparison
2645 * XMLRPC_SetDefaultIdCaseComparison
2647 * XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare )
2649 * Gets default case comparison options used by XMLRPC_VALUE funcs
2651 * id_case_compare case comparison rule to set as default
2653 * XMLRPC_CASE_COMPARISON newly set default
2655 * Nasty and gross. Should be server specific, but that requires changing all
2656 * the XMLRPC_VALUE api's.
2658 * XMLRPC_GetDefaultIdCaseComparison ()
2661 XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) {
2662 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2663 options->id_case_compare = id_case_compare;
2664 return options->id_case_compare;
2669 /*-*********************************
2670 * End XMLRPC General Options funcs *
2671 ***********************************/
2674 /*-******************
2676 ********************/
2678 /****f* UTILITY/XMLRPC_UtilityCreateFault
2680 * XMLRPC_UtilityCreateFault
2682 * XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string )
2684 * generates a struct containing a string member with id "faultString" and an int member
2685 * with id "faultCode". When using the xmlrpc xml serialization, these will be translated
2686 * to <fault><value><struct>... format.
2688 * fault_code application specific error code. can be 0.
2689 * fault_string application specific error string. cannot be null.
2691 * XMLRPC_VALUE a newly created struct vector representing the error, or null on error.
2693 * This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc
2694 * API or data structures. It is the author's view, that this API is intended for simple
2695 * data types, and a "fault" is a complex data type consisting of multiple simple data
2696 * types. This function is provided for convenience only, the same result could be
2697 * achieved directly by the application.
2699 * This function now supports some "standardized" fault codes, as specified at.
2700 * http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
2701 * If one of these fault codes is received, the description string will automatically
2702 * be prefixed with a standard error string and 2 newlines.
2704 * The actual transformation between this complex type and the xml "<fault>" element takes
2705 * place in the xmlrpc to xml serialization layer. This step is not performed when using the
2706 * simplerpc serialization, meaning that there will be no "<fault>" element in that
2707 * serialization. There will simply be a standard struct with 2 child elements.
2708 * imho, the "<fault>" element is unnecessary and/or out of place as part of the standard API.
2712 XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) {
2713 XMLRPC_VALUE xOutput = NULL;
2715 char* string = NULL;
2716 simplestring description;
2717 simplestring_init(&description);
2719 switch (fault_code) {
2720 case xmlrpc_error_parse_xml_syntax:
2721 string = xmlrpc_error_parse_xml_syntax_str;
2723 case xmlrpc_error_parse_unknown_encoding:
2724 string = xmlrpc_error_parse_unknown_encoding_str;
2726 case xmlrpc_error_parse_bad_encoding:
2727 string = xmlrpc_error_parse_bad_encoding_str;
2729 case xmlrpc_error_invalid_xmlrpc:
2730 string = xmlrpc_error_invalid_xmlrpc_str;
2732 case xmlrpc_error_unknown_method:
2733 string = xmlrpc_error_unknown_method_str;
2735 case xmlrpc_error_invalid_params:
2736 string = xmlrpc_error_invalid_params_str;
2738 case xmlrpc_error_internal_server:
2739 string = xmlrpc_error_internal_server_str;
2741 case xmlrpc_error_application:
2742 string = xmlrpc_error_application_str;
2744 case xmlrpc_error_system:
2745 string = xmlrpc_error_system_str;
2747 case xmlrpc_error_transport:
2748 string = xmlrpc_error_transport_str;
2752 simplestring_add(&description, string);
2754 if(string && fault_string) {
2755 simplestring_add(&description, "\n\n");
2757 simplestring_add(&description, fault_string);
2760 if(description.len) {
2761 xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
2763 XMLRPC_VectorAppendString (xOutput, "faultString", description.str,
2765 XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code);
2768 simplestring_free(&description);
2776 /****f* FAULT/XMLRPC_ValueIsFault
2778 * XMLRPC_ValueIsFault
2780 * int XMLRPC_ValueIsFault (XMLRPC_VALUE value)
2782 * Determines if a value encapsulates a fault "object"
2784 * value any XMLRPC_VALUE
2786 * 1 if it is a fault, else 0
2788 * XMLRPC_ResponseIsFault ()
2791 int XMLRPC_ValueIsFault (XMLRPC_VALUE value) {
2792 if( XMLRPC_VectorGetValueWithID(value, "faultCode") &&
2793 XMLRPC_VectorGetValueWithID(value, "faultString") ) {
2801 /****f* FAULT/XMLRPC_ResponseIsFault
2803 * XMLRPC_ResponseIsFault
2805 * int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response)
2807 * Determines if a response contains an encapsulated fault "object"
2809 * value any XMLRPC_REQUEST. typically of type xmlrpc_request_response
2811 * 1 if it contains a fault, else 0
2813 * XMLRPC_ValueIsFault ()
2816 int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) {
2817 return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) );
2822 /****f* FAULT/XMLRPC_GetValueFaultCode
2824 * XMLRPC_GetValueFaultCode
2826 * int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value)
2828 * returns fault code from a struct, if any
2830 * value XMLRPC_VALUE of type xmlrpc_vector_struct.
2832 * fault code, else 0.
2834 * impossible to distinguish faultCode == 0 from faultCode not present.
2836 * XMLRPC_GetResponseFaultCode ()
2839 int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) {
2840 return XMLRPC_VectorGetIntWithID(value, "faultCode");
2845 /****f* FAULT/XMLRPC_GetResponseFaultCode
2847 * XMLRPC_GetResponseFaultCode
2849 * int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)
2851 * returns fault code from a response, if any
2853 * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2855 * fault code, else 0.
2857 * impossible to distinguish faultCode == 0 from faultCode not present.
2859 * XMLRPC_GetValueFaultCode ()
2862 int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) {
2863 return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) );
2869 /****f* FAULT/XMLRPC_GetValueFaultString
2871 * XMLRPC_GetValueFaultString
2873 * const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value)
2875 * returns fault string from a struct, if any
2877 * value XMLRPC_VALUE of type xmlrpc_vector_struct.
2879 * fault string, else 0.
2881 * XMLRPC_GetResponseFaultString ()
2884 const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) {
2885 return XMLRPC_VectorGetStringWithID(value, "faultString");
2890 /****f* FAULT/XMLRPC_GetResponseFaultString
2892 * XMLRPC_GetResponseFaultString
2894 * const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response)
2896 * returns fault string from a response, if any
2898 * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2900 * fault string, else 0.
2902 * XMLRPC_GetValueFaultString ()
2905 const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) {
2906 return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) );
2912 /*-******************
2913 * Utility API funcs *
2914 ********************/
2917 /****f* UTILITY/XMLRPC_Free
2921 * void XMLRPC_Free(void* mem)
2923 * frees a block of memory allocated by xmlrpc.
2925 * mem memory to free
2929 * Useful for OS's where memory must be free'd
2930 * in the same library in which it is allocated.
2933 void XMLRPC_Free(void* mem) {
2940 /****f* UTILITY/XMLRPC_GetVersionString
2942 * XMLRPC_GetVersionString
2944 * const char* XMLRPC_GetVersionString()
2946 * returns library version string
2954 const char* XMLRPC_GetVersionString() {
2955 return XMLRPC_VERSION_STR;
2961 /*-**********************
2962 * End Utility API funcs *
2963 ************************/