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: xmlrpc.c,v 1.6 2004/04/27 17:33:59 iliaa Exp $";
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) {
1113 case xmlrpc_boolean:
1114 case xmlrpc_datetime:
1119 /* Guard against putting a key/val pair into an array vector */
1120 if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) {
1121 if (isDuplicateEntry (target, source)
1122 || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) {
1128 "xmlrpc: attempted to add key/val pair to vector of type array\n");
1133 "xmlrpc: attempted to add value of unknown type to vector\n");
1144 /****f* VECTOR/XMLRPC_AddValuesToVector
1146 * XMLRPC_AddValuesToVector
1148 * XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 )
1149 * XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... )
1151 * Add (append) a series of existing XMLRPC_VALUE to a vector.
1153 * target The target vector
1154 * ... The source value(s) to append. The last item *must* be 0.
1156 * int 1 if successful, else 0
1158 * XMLRPC_AddValuesToVector ()
1159 * XMLRPC_VectorGetValueWithID_Case ()
1162 * This function may actually return failure after it has already modified
1163 * or added items to target. You can not trust the state of target
1164 * if this function returns failure.
1167 int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) {
1171 if(target->type == xmlrpc_vector) {
1172 XMLRPC_VALUE v = NULL;
1175 va_start(vl, target);
1178 v = va_arg(vl, XMLRPC_VALUE);
1180 if(!XMLRPC_AddValueToVector(target, v)) {
1201 /****f* VECTOR/XMLRPC_VectorGetValueWithID_Case
1203 * XMLRPC_VectorGetValueWithID_Case
1205 * XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case)
1207 * Get value from vector matching id (key)
1209 * vector The source vector
1210 * id The key to find
1211 * id_case Rule for how to match key
1213 * int 1 if successful, else 0
1215 * XMLRPC_SetValueID_Case ()
1217 * XMLRPC_CASE_COMPARISON
1220 XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id,
1221 XMLRPC_CASE_COMPARISON id_case) {
1222 if(vector && vector->v && vector->v->q) {
1223 q_iter qi = Q_Iter_Head_F(vector->v->q);
1226 XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1227 if(xIter && xIter->id.str) {
1228 if(id_case == xmlrpc_case_sensitive) {
1229 if(!strcmp(xIter->id.str, id)) {
1233 else if(id_case == xmlrpc_case_insensitive) {
1234 if(!strcasecmp(xIter->id.str, id)) {
1239 qi = Q_Iter_Next_F(qi);
1248 int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) {
1249 if(vector && vector->v && vector->v->q && value) {
1250 q_iter qi = Q_Iter_Head_F(vector->v->q);
1253 XMLRPC_VALUE xIter = Q_Iter_Get_F(qi);
1254 if(xIter == value) {
1255 XMLRPC_CleanupValue(xIter);
1256 Q_Iter_Del(vector->v->q, qi);
1259 qi = Q_Iter_Next_F(qi);
1266 /****f* VALUE/XMLRPC_CreateValueString
1268 * XMLRPC_CreateValueString
1270 * XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len)
1272 * Create an XMLRPC_VALUE, and assign a string to it
1274 * id The id of the value, or NULL
1275 * val The desired new string val.
1276 * len length of val string if known, or 0 if unknown.
1278 * newly allocated XMLRPC_VALUE, or NULL
1280 * XMLRPC_GetValueString ()
1281 * XMLRPC_CreateValueEmpty ()
1286 XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) {
1287 XMLRPC_VALUE value = NULL;
1289 value = XMLRPC_CreateValueEmpty();
1291 XMLRPC_SetValueString(value, val, len);
1293 XMLRPC_SetValueID(value, id, 0);
1302 /****f* VALUE/XMLRPC_CreateValueInt
1304 * XMLRPC_CreateValueInt
1306 * XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i)
1308 * Create an XMLRPC_VALUE, and assign an int to it
1310 * id The id of the value, or NULL
1311 * i The desired new int val.
1313 * newly allocated XMLRPC_VALUE, or NULL
1315 * XMLRPC_GetValueInt ()
1316 * XMLRPC_CreateValueEmpty ()
1321 XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) {
1322 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1324 XMLRPC_SetValueInt(val, i);
1326 XMLRPC_SetValueID(val, id, 0);
1334 /****f* VALUE/XMLRPC_CreateValueBoolean
1336 * XMLRPC_CreateValueBoolean
1338 * XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i)
1340 * Create an XMLRPC_VALUE, and assign an int to it
1342 * id The id of the value, or NULL
1343 * i The desired new int val.
1345 * newly allocated XMLRPC_VALUE, or NULL
1347 * XMLRPC_GetValueBoolean ()
1348 * XMLRPC_CreateValueEmpty ()
1353 XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) {
1354 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1356 XMLRPC_SetValueBoolean(val, i);
1358 XMLRPC_SetValueID(val, id, 0);
1367 /****f* VALUE/XMLRPC_CleanupValue
1369 * XMLRPC_CleanupValue
1371 * void XMLRPC_CleanupValue(XMLRPC_VALUE value)
1373 * Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector)
1375 * value The id of the value to be cleaned up.
1379 * Normally this function will be called for the topmost vector, thus free-ing
1380 * all children. If a child of a vector is free'd first, results are undefined.
1381 * Failure to call this function *will* cause memory leaks.
1383 * Also, this function is implemented using reference counting. Thus a value
1384 * may be added and freed from multiple parents so long as a reference is added
1385 * first using XMLRPC_CopyValue()
1387 * XMLRPC_RequestFree ()
1388 * XMLRPC_CreateValueEmpty ()
1389 * XMLRPC_CopyValue()
1393 void XMLRPC_CleanupValue(XMLRPC_VALUE value) {
1395 if(value->iRefCount > 0) {
1396 value->iRefCount --;
1399 #ifdef XMLRPC_DEBUG_REFCOUNT
1401 printf ("decremented refcount of %s, now %i\n", value->id.str,
1405 printf ("decremented refcount of 0x%x, now %i\n", value,
1410 if(value->type == xmlrpc_vector) {
1412 if(value->iRefCount == 0) {
1413 XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q);
1415 XMLRPC_CleanupValue(cur);
1417 /* Make sure some idiot didn't include a vector as a child of itself
1418 * and thus it would have already free'd these.
1420 if(value->v && value->v->q) {
1421 cur = Q_Next(value->v->q);
1428 Q_Destroy(value->v->q);
1429 my_free(value->v->q);
1436 if(value->iRefCount == 0) {
1438 /* guard against freeing invalid types */
1439 switch(value->type) {
1442 case xmlrpc_boolean:
1443 case xmlrpc_datetime:
1448 #ifdef XMLRPC_DEBUG_REFCOUNT
1450 printf("free'd %s\n", value->id.str);
1453 printf("free'd 0x%x\n", value);
1456 simplestring_free(&value->id);
1457 simplestring_free(&value->str);
1459 memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE));
1464 "xmlrpc: attempted to free value of invalid type\n");
1474 /****f* VALUE/XMLRPC_SetValueDateTime
1476 * XMLRPC_SetValueDateTime
1478 * void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time)
1480 * Assign time value to XMLRPC_VALUE
1482 * value The target XMLRPC_VALUE
1483 * time The desired new unix time value (time_t)
1487 * XMLRPC_GetValueDateTime ()
1488 * XMLRPC_SetValueDateTime_ISO8601 ()
1489 * XMLRPC_CreateValueDateTime ()
1493 void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) {
1496 value->type = xmlrpc_datetime;
1501 date_to_ISO8601(time, timeBuf, sizeof(timeBuf));
1504 simplestring_clear(&value->str);
1505 simplestring_add(&value->str, timeBuf);
1512 /****f* VALUE/XMLRPC_CopyValue
1516 * XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value)
1518 * Make a copy (reference) of an XMLRPC_VALUE
1520 * value The target XMLRPC_VALUE
1522 * XMLRPC_VALUE -- address of the copy
1524 * XMLRPC_CleanupValue ()
1525 * XMLRPC_DupValueNew ()
1527 * This function is implemented via reference counting, so the
1528 * returned value is going to be the same as the passed in value.
1529 * The value must be freed the same number of times it is copied
1530 * or there will be a memory leak.
1533 XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) {
1535 value->iRefCount ++;
1536 #ifdef XMLRPC_DEBUG_REFCOUNT
1538 printf ("incremented refcount of %s, now %i\n", value->id.str,
1542 printf ("incremented refcount of 0x%x, now %i\n", value,
1553 /****f* VALUE/XMLRPC_DupValueNew
1555 * XMLRPC_DupValueNew
1557 * XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value)
1559 * Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem.
1561 * value The source XMLRPC_VALUE to duplicate
1563 * XMLRPC_VALUE -- address of the duplicate value
1565 * XMLRPC_CleanupValue ()
1566 * XMLRPC_CopyValue ()
1568 * Use this when function when you need to modify the contents of
1569 * the copied value seperately from the original.
1571 * this function is recursive, thus the value and all of its children
1572 * (if any) will be duplicated.
1575 XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) {
1576 XMLRPC_VALUE xReturn = NULL;
1578 xReturn = XMLRPC_CreateValueEmpty ();
1579 if (xSource->id.len) {
1580 XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len);
1583 switch (xSource->type) {
1585 case xmlrpc_boolean:
1586 XMLRPC_SetValueInt (xReturn, xSource->i);
1590 XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len);
1592 case xmlrpc_datetime:
1593 XMLRPC_SetValueDateTime (xReturn, xSource->i);
1596 XMLRPC_SetValueDouble (xReturn, xSource->d);
1600 q_iter qi = Q_Iter_Head_F (xSource->v->q);
1601 XMLRPC_SetIsVector (xReturn, xSource->v->type);
1604 XMLRPC_VALUE xIter = Q_Iter_Get_F (qi);
1605 XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter));
1606 qi = Q_Iter_Next_F (qi);
1621 /****f* VALUE/XMLRPC_CreateValueDateTime
1623 * XMLRPC_CreateValueDateTime
1625 * XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time)
1627 * Create new datetime value from time_t
1629 * id id of the new value, or NULL
1630 * time The desired unix time value (time_t)
1634 * XMLRPC_GetValueDateTime ()
1635 * XMLRPC_SetValueDateTime ()
1636 * XMLRPC_CreateValueDateTime_ISO8601 ()
1640 XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) {
1641 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1643 XMLRPC_SetValueDateTime(val, time);
1645 XMLRPC_SetValueID(val, id, 0);
1654 /****f* VALUE/XMLRPC_SetValueDateTime_ISO8601
1656 * XMLRPC_SetValueDateTime_ISO8601
1658 * void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s)
1660 * Set datetime value from IS08601 encoded string
1662 * value The target XMLRPC_VALUE
1663 * s The desired new time value
1667 * This function currently attempts to convert the time string to a valid unix time
1668 * value before passing it. Behavior when the string is invalid or out of range
1669 * is not well defined, but will probably result in Jan 1, 1970 (0) being passed.
1671 * XMLRPC_GetValueDateTime_ISO8601 ()
1672 * XMLRPC_CreateValueDateTime_ISO8601 ()
1673 * XMLRPC_CreateValueDateTime ()
1677 void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) {
1679 time_t time_val = 0;
1681 date_from_ISO8601(s, &time_val);
1682 XMLRPC_SetValueDateTime(value, time_val);
1689 /****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601
1691 * XMLRPC_CreateValueDateTime_ISO8601
1693 * XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s)
1695 * Create datetime value from IS08601 encoded string
1697 * id The id of the new value, or NULL
1698 * s The desired new time value
1700 * newly allocated XMLRPC_VALUE, or NULL if no value created.
1702 * See XMLRPC_SetValueDateTime_ISO8601 ()
1704 * XMLRPC_GetValueDateTime_ISO8601 ()
1705 * XMLRPC_SetValueDateTime_ISO8601 ()
1706 * XMLRPC_CreateValueDateTime ()
1710 XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) {
1711 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1713 XMLRPC_SetValueDateTime_ISO8601(val, s);
1715 XMLRPC_SetValueID(val, id, 0);
1724 /****f* VALUE/XMLRPC_SetValueBase64
1726 * XMLRPC_SetValueBase64
1728 * void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len)
1730 * Set base64 value. Base64 is useful for transferring binary data, such as an image.
1732 * value The target XMLRPC_VALUE
1733 * s The desired new binary value
1734 * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1738 * Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and
1739 * decoded on the other side. This is transparent to the caller.
1741 * XMLRPC_GetValueBase64 ()
1742 * XMLRPC_CreateValueBase64 ()
1746 void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) {
1748 simplestring_clear(&value->str);
1749 (len > 0) ? simplestring_addn(&value->str, s, len) :
1750 simplestring_add(&value->str, s);
1751 value->type = xmlrpc_base64;
1758 /****f* VALUE/XMLRPC_CreateValueBase64
1760 * XMLRPC_CreateValueBase64
1762 * XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len)
1764 * Create base64 value. Base64 is useful for transferring binary data, such as an image.
1766 * id id of the new value, or NULL
1767 * s The desired new binary value
1768 * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed.
1770 * newly allocated XMLRPC_VALUE, or NULL if error
1772 * See XMLRPC_SetValueBase64 ()
1774 * XMLRPC_GetValueBase64 ()
1775 * XMLRPC_SetValueBase64 ()
1779 XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) {
1780 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1782 XMLRPC_SetValueBase64(val, s, len);
1784 XMLRPC_SetValueID(val, id, 0);
1792 /****f* VALUE/XMLRPC_SetValueDouble
1794 * XMLRPC_SetValueDouble
1796 * void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val)
1798 * Set double (floating point) value.
1800 * value The target XMLRPC_VALUE
1801 * val The desired new double value
1805 * XMLRPC_GetValueDouble ()
1806 * XMLRPC_CreateValueDouble ()
1810 void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) {
1812 value->type = xmlrpc_double;
1819 /****f* VALUE/XMLRPC_CreateValueDouble
1821 * XMLRPC_CreateValueDouble
1823 * XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d)
1825 * Create double (floating point) value.
1827 * id id of the newly created value, or NULL
1828 * d The desired new double value
1832 * XMLRPC_GetValueDouble ()
1833 * XMLRPC_CreateValueDouble ()
1837 XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) {
1838 XMLRPC_VALUE val = XMLRPC_CreateValueEmpty();
1840 XMLRPC_SetValueDouble(val, d);
1842 XMLRPC_SetValueID(val, id, 0);
1850 /****f* VALUE/XMLRPC_GetValueString
1852 * XMLRPC_GetValueString
1854 * const char* XMLRPC_GetValueString(XMLRPC_VALUE value)
1856 * retrieve string value
1858 * value source XMLRPC_VALUE of type xmlrpc_string
1862 * XMLRPC_SetValueString ()
1863 * XMLRPC_GetValueType ()
1867 const char* XMLRPC_GetValueString(XMLRPC_VALUE value) {
1868 return ((value && value->type == xmlrpc_string) ? value->str.str : 0);
1873 /****f* VALUE/XMLRPC_GetValueStringLen
1875 * XMLRPC_GetValueStringLen
1877 * int XMLRPC_GetValueStringLen(XMLRPC_VALUE value)
1879 * determine length of string value
1881 * value XMLRPC_VALUE of type xmlrpc_string
1883 * length of string, or 0
1886 * XMLRPC_SetValueString ()
1887 * XMLRPC_GetValueString ()
1890 int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) {
1891 return ((value) ? value->str.len : 0);
1896 /****f* VALUE/XMLRPC_GetValueInt
1898 * XMLRPC_GetValueInt
1900 * int XMLRPC_GetValueInt(XMLRPC_VALUE value)
1902 * retrieve integer value.
1904 * value XMLRPC_VALUE of type xmlrpc_int
1906 * integer value or 0 if value is not valid int
1908 * use XMLRPC_GetValueType () to be sure if 0 is real return value or not
1910 * XMLRPC_SetValueInt ()
1911 * XMLRPC_CreateValueInt ()
1914 int XMLRPC_GetValueInt(XMLRPC_VALUE value) {
1915 return ((value && value->type == xmlrpc_int) ? value->i : 0);
1920 /****f* VALUE/XMLRPC_GetValueBoolean
1922 * XMLRPC_GetValueBoolean
1924 * int XMLRPC_GetValueBoolean(XMLRPC_VALUE value)
1926 * retrieve boolean value.
1928 * XMLRPC_VALUE of type xmlrpc_boolean
1930 * boolean value or 0 if value is not valid boolean
1932 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
1934 * XMLRPC_SetValueBoolean ()
1935 * XMLRPC_CreateValueBoolean ()
1938 int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) {
1939 return ((value && value->type == xmlrpc_boolean) ? value->i : 0);
1944 /****f* VALUE/XMLRPC_GetValueDouble
1946 * XMLRPC_GetValueDouble
1948 * double XMLRPC_GetValueDouble(XMLRPC_VALUE value)
1950 * retrieve double value
1952 * XMLRPC_VALUE of type xmlrpc_double
1954 * double value or 0 if value is not valid double.
1956 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
1958 * XMLRPC_SetValueDouble ()
1959 * XMLRPC_CreateValueDouble ()
1962 double XMLRPC_GetValueDouble(XMLRPC_VALUE value) {
1963 return ((value && value->type == xmlrpc_double) ? value->d : 0);
1968 /****f* VALUE/XMLRPC_GetValueBase64
1970 * XMLRPC_GetValueBase64
1972 * const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value)
1974 * retrieve binary value
1976 * XMLRPC_VALUE of type xmlrpc_base64
1978 * pointer to binary value or 0 if value is not valid.
1980 * XMLRPC_SetValueBase64 ()
1981 * XMLRPC_CreateValueBase64 ()
1983 * Call XMLRPC_GetValueStringLen() to retrieve real length of binary data. strlen()
1984 * will not be accurate, as returned data may contain embedded nulls.
1987 const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) {
1988 return ((value && value->type == xmlrpc_base64) ? value->str.str : 0);
1993 /****f* VALUE/XMLRPC_GetValueDateTime
1995 * XMLRPC_GetValueDateTime
1997 * time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value)
1999 * retrieve time_t value
2001 * XMLRPC_VALUE of type xmlrpc_datetime
2003 * time_t value or 0 if value is not valid datetime.
2005 * use XMLRPC_GetValueType() to be sure if 0 is real value or not
2007 * XMLRPC_SetValueDateTime ()
2008 * XMLRPC_GetValueDateTime_ISO8601 ()
2009 * XMLRPC_CreateValueDateTime ()
2012 time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) {
2013 return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0);
2018 /****f* VALUE/XMLRPC_GetValueDateTime_IOS8601
2020 * XMLRPC_GetValueDateTime_IOS8601
2022 * const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value)
2024 * retrieve ISO8601 formatted time value
2026 * XMLRPC_VALUE of type xmlrpc_datetime
2028 * const char* value or 0 if value is not valid datetime.
2030 * XMLRPC_SetValueDateTime_IOS8601 ()
2031 * XMLRPC_GetValueDateTime ()
2032 * XMLRPC_CreateValueDateTime_IOS8601 ()
2035 const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) {
2036 return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0);
2041 /* Get ID (key) of value or NULL */
2042 /****f* VALUE/XMLRPC_GetValueID
2046 * const char* XMLRPC_GetValueID(XMLRPC_VALUE value)
2048 * retrieve id (key) of value
2050 * XMLRPC_VALUE of any type
2052 * const char* pointer to id of value, or NULL
2055 * XMLRPC_SetValueID()
2056 * XMLRPC_CreateValueEmpty()
2059 const char* XMLRPC_GetValueID(XMLRPC_VALUE value) {
2060 return (const char*)((value && value->id.len) ? value->id.str : 0);
2066 /****f* VECTOR/XMLRPC_VectorSize
2070 * int XMLRPC_VectorSize(XMLRPC_VALUE value)
2072 * retrieve size of vector
2074 * XMLRPC_VALUE of type xmlrpc_vector
2076 * count of items in vector
2078 * This is a cheap operation even on large vectors. Vector size is
2079 * maintained by queue during add/remove ops.
2081 * XMLRPC_AddValueToVector ()
2084 int XMLRPC_VectorSize(XMLRPC_VALUE value) {
2086 if(value && value->type == xmlrpc_vector && value->v) {
2087 size = Q_Size(value->v->q);
2094 /****f* VECTOR/XMLRPC_VectorRewind
2096 * XMLRPC_VectorRewind
2098 * XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value)
2100 * reset vector to first item
2102 * XMLRPC_VALUE of type xmlrpc_vector
2104 * first XMLRPC_VALUE in list, or NULL if empty or error.
2106 * Be careful to rewind any vector passed in to you if you expect to
2107 * iterate through the entire list.
2109 * XMLRPC_VectorNext ()
2112 XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) {
2113 XMLRPC_VALUE xReturn = NULL;
2114 if(value && value->type == xmlrpc_vector && value->v) {
2115 xReturn = (XMLRPC_VALUE)Q_Head(value->v->q);
2122 /****f* VECTOR/XMLRPC_VectorNext
2126 * XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value)
2128 * Iterate vector to next item in list.
2130 * XMLRPC_VALUE of type xmlrpc_vector
2132 * Next XMLRPC_VALUE in vector, or NULL if at end.
2135 * XMLRPC_VectorRewind ()
2138 XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) {
2139 XMLRPC_VALUE xReturn = NULL;
2140 if(value && value->type == xmlrpc_vector && value->v) {
2141 xReturn = (XMLRPC_VALUE)Q_Next(value->v->q);
2148 /****f* VALUE/XMLRPC_GetValueType
2150 * XMLRPC_GetValueType
2152 * XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value)
2154 * determine data type of the XMLRPC_VALUE
2156 * XMLRPC_VALUE target of query
2158 * data type of value as enumerated by XMLRPC_VALUE_TYPE
2160 * all values are of type xmlrpc_empty until set.
2161 * Deprecated for public use. See XMLRPC_GetValueTypeEasy
2164 * XMLRPC_CreateValue*
2166 * XMLRPC_GetValueTypeEasy ()
2169 XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) {
2170 return value ? value->type : xmlrpc_empty;
2175 /* Vector type accessor */
2176 /****f* VALUE/XMLRPC_GetVectorType
2178 * XMLRPC_GetVectorType
2180 * XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value)
2182 * determine vector type of the XMLRPC_VALUE
2184 * XMLRPC_VALUE of type xmlrpc_vector
2186 * vector type of value as enumerated by XMLRPC_VECTOR_TYPE.
2187 * xmlrpc_none if not a value.
2189 * xmlrpc_none is returned if value is not a vector
2190 * Deprecated for public use. See XMLRPC_GetValueTypeEasy
2192 * XMLRPC_SetIsVector ()
2193 * XMLRPC_GetValueType ()
2194 * XMLRPC_GetValueTypeEasy ()
2197 XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) {
2198 return(value && value->v) ? value->v->type : xmlrpc_none;
2203 /****f* VALUE/XMLRPC_GetValueTypeEasy
2205 * XMLRPC_GetValueTypeEasy
2207 * XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value)
2209 * determine data type of the XMLRPC_VALUE. includes vector types.
2211 * XMLRPC_VALUE target of query
2213 * data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY
2214 * xmlrpc_type_none if not a value.
2216 * all values are of type xmlrpc_type_empty until set.
2219 * XMLRPC_CreateValue*
2223 XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) {
2225 switch (value->type) {
2227 switch (value->v->type) {
2228 case xmlrpc_vector_none:
2229 return xmlrpc_type_none;
2230 case xmlrpc_vector_struct:
2231 return xmlrpc_type_struct;
2232 case xmlrpc_vector_mixed:
2233 return xmlrpc_type_mixed;
2234 case xmlrpc_vector_array:
2235 return xmlrpc_type_array;
2238 /* evil cast, but we know they are the same */
2239 return(XMLRPC_VALUE_TYPE_EASY) value->type;
2249 /*-*******************
2250 * Begin Server Funcs *
2251 *********************/
2254 /****f* VALUE/XMLRPC_ServerCreate
2256 * XMLRPC_ServerCreate
2258 * XMLRPC_SERVER XMLRPC_ServerCreate()
2260 * Allocate/Init XMLRPC Server Resources.
2264 * newly allocated XMLRPC_SERVER
2267 * XMLRPC_ServerDestroy ()
2268 * XMLRPC_GetGlobalServer ()
2271 XMLRPC_SERVER XMLRPC_ServerCreate() {
2272 XMLRPC_SERVER server = calloc(1, sizeof(STRUCT_XMLRPC_SERVER));
2274 Q_Init(&server->methodlist);
2275 Q_Init(&server->docslist);
2277 /* register system methods */
2278 xsm_register(server);
2285 /* Return global server. Not locking! Not Thread Safe! */
2286 /****f* VALUE/XMLRPC_GetGlobalServer
2288 * XMLRPC_GetGlobalServer
2290 * XMLRPC_SERVER XMLRPC_GetGlobalServer()
2292 * Allocates a global (process-wide) server, or returns pointer if pre-existing.
2296 * pointer to global server, or 0 if error.
2298 * ***WARNING*** This function is not thread safe. It is included only for the very lazy.
2299 * Multi-threaded programs that use this may experience problems.
2301 * There is currently no way to cleanup the global server gracefully.
2303 * XMLRPC_ServerCreate ()
2306 XMLRPC_SERVER XMLRPC_GetGlobalServer() {
2307 static XMLRPC_SERVER xsServer = 0;
2309 xsServer = XMLRPC_ServerCreate();
2316 /****f* VALUE/XMLRPC_ServerDestroy
2318 * XMLRPC_ServerDestroy
2320 * void XMLRPC_ServerDestroy(XMLRPC_SERVER server)
2322 * Free Server Resources
2324 * server The server to be free'd
2328 * This frees the server struct and any methods that have been added.
2330 * XMLRPC_ServerCreate ()
2333 void XMLRPC_ServerDestroy(XMLRPC_SERVER server) {
2335 doc_method* dm = Q_Head(&server->docslist);
2336 server_method* sm = Q_Head(&server->methodlist);
2339 dm = Q_Next(&server->docslist);
2346 XMLRPC_CleanupValue(sm->desc);
2349 sm = Q_Next(&server->methodlist);
2351 if(server->xIntrospection) {
2352 XMLRPC_CleanupValue(server->xIntrospection);
2355 Q_Destroy(&server->methodlist);
2356 Q_Destroy(&server->docslist);
2364 /****f* VALUE/XMLRPC_ServerRegisterMethod
2366 * XMLRPC_ServerRegisterMethod
2368 * void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb)
2370 * Register new XMLRPC method with server
2372 * server The XMLRPC_SERVER to register the method with
2373 * name public name of the method
2374 * cb C function that implements the method
2376 * int - 1 if success, else 0
2378 * A C function must be registered for every "method" that the server recognizes. The
2379 * method name is equivalent to <methodCall><name> method name </name></methodCall> in the
2382 * XMLRPC_ServerFindMethod ()
2383 * XMLRPC_ServerCallMethod ()
2386 int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) {
2387 if(server && name && cb) {
2389 server_method* sm = malloc(sizeof(server_method));
2392 sm->name = strdup(name);
2396 return Q_PushTail(&server->methodlist, sm);
2404 server_method* find_method(XMLRPC_SERVER server, const char* name) {
2407 q_iter qi = Q_Iter_Head_F(&server->methodlist);
2410 sm = Q_Iter_Get_F(qi);
2411 if(sm && !strcmp(sm->name, name)) {
2414 qi = Q_Iter_Next_F(qi);
2420 const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) {
2428 case xmlrpc_boolean:
2430 case xmlrpc_datetime:
2440 case xmlrpc_vector_none:
2442 case xmlrpc_vector_array:
2444 case xmlrpc_vector_mixed:
2445 return "mixed vector (struct)";
2446 case xmlrpc_vector_struct:
2453 /****f* VALUE/XMLRPC_ServerFindMethod
2455 * XMLRPC_ServerFindMethod
2457 * XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName)
2459 * retrieve C callback associated with a given method name.
2461 * server The XMLRPC_SERVER the method is registered with
2462 * callName the method to find
2464 * previously registered XMLRPC_Callback, or NULL
2466 * Typically, this is used to determine if a requested method exists, without actually calling it.
2468 * XMLRPC_ServerCallMethod ()
2469 * XMLRPC_ServerRegisterMethod ()
2472 XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) {
2473 if(server && callName) {
2474 q_iter qi = Q_Iter_Head_F(&server->methodlist);
2476 server_method* sm = Q_Iter_Get_F(qi);
2477 if(sm && !strcmp(sm->name, callName)) {
2480 qi = Q_Iter_Next_F(qi);
2489 /* Call method specified in request */
2490 /****f* VALUE/XMLRPC_ServerCallMethod
2492 * XMLRPC_ServerCallMethod
2494 * XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData)
2498 * server The XMLRPC_SERVER the method is registered with
2499 * request the request to handle
2500 * userData any additional data to pass to the C callback, or NULL
2502 * XMLRPC_VALUE allocated by the callback, or NULL
2504 * It is typically the caller's responsibility to free the returned value.
2506 * Often the caller will want to serialize the result as XML, via
2507 * XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML ()
2509 * XMLRPC_ServerFindMethod ()
2510 * XMLRPC_ServerRegisterMethod ()
2511 * XMLRPC_CleanupValue ()
2514 XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) {
2515 XMLRPC_VALUE xReturn = NULL;
2517 /* check for error set during request parsing / generation */
2518 if(request && request->error) {
2519 xReturn = XMLRPC_CopyValue(request->error);
2521 else if (server && request) {
2522 XMLRPC_Callback cb =
2523 XMLRPC_ServerFindMethod (server, request->methodName.str);
2525 xReturn = cb(server, request, userData);
2529 XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method,
2530 request->methodName.str);
2538 /*-*****************
2539 * End server funcs *
2540 *******************/
2543 /*-***********************************
2544 * Begin XMLRPC General Options funcs *
2545 *************************************/
2547 /* For options used by XMLRPC_VALUE funcs that otherwise do not have
2548 * parameters for options. Kind of gross. :(
2550 typedef struct _xmlrpc_options {
2551 XMLRPC_CASE id_case;
2552 XMLRPC_CASE_COMPARISON id_case_compare;
2554 STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS;
2556 static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() {
2557 static STRUCT_XMLRPC_OPTIONS options = {
2559 xmlrpc_case_sensitive
2564 /****f* VALUE/XMLRPC_GetDefaultIdCase
2566 * XMLRPC_GetDefaultIdCase
2568 * XMLRPC_CASE XMLRPC_GetDefaultIdCase()
2570 * Gets default case options used by XMLRPC_VALUE funcs
2576 * Nasty and gross. Should be server specific, but that requires changing all
2577 * the XMLRPC_VALUE api's.
2579 * XMLRPC_SetDefaultIdCase ()
2582 XMLRPC_CASE XMLRPC_GetDefaultIdCase() {
2583 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2584 return options->id_case;
2589 /****f* VALUE/XMLRPC_SetDefaultIdCase
2591 * XMLRPC_SetDefaultIdCase
2593 * XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case)
2595 * Sets default case options used by XMLRPC_VALUE funcs
2597 * id_case case options as enumerated by XMLRPC_CASE
2599 * XMLRPC_CASE -- newly set option
2601 * Nasty and gross. Should be server specific, but that requires changing all
2602 * the XMLRPC_VALUE api's.
2604 * XMLRPC_GetDefaultIdCase ()
2607 XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) {
2608 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2609 options->id_case = id_case;
2610 return options->id_case;
2615 /****f* VALUE/XMLRPC_GetDefaultIdCaseComparison
2617 * XMLRPC_GetDefaultIdCaseComparison
2619 * XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( )
2621 * Gets default case comparison options used by XMLRPC_VALUE funcs
2625 * XMLRPC_CASE_COMPARISON default
2627 * Nasty and gross. Should be server specific, but that requires changing all
2628 * the XMLRPC_VALUE api's.
2630 * XMLRPC_SetDefaultIdCaseComparison ()
2633 XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() {
2634 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2635 return options->id_case_compare;
2640 /****f* VALUE/XMLRPC_SetDefaultIdCaseComparison
2642 * XMLRPC_SetDefaultIdCaseComparison
2644 * XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare )
2646 * Gets default case comparison options used by XMLRPC_VALUE funcs
2648 * id_case_compare case comparison rule to set as default
2650 * XMLRPC_CASE_COMPARISON newly set default
2652 * Nasty and gross. Should be server specific, but that requires changing all
2653 * the XMLRPC_VALUE api's.
2655 * XMLRPC_GetDefaultIdCaseComparison ()
2658 XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) {
2659 XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions();
2660 options->id_case_compare = id_case_compare;
2661 return options->id_case_compare;
2666 /*-*********************************
2667 * End XMLRPC General Options funcs *
2668 ***********************************/
2671 /*-******************
2673 ********************/
2675 /****f* UTILITY/XMLRPC_UtilityCreateFault
2677 * XMLRPC_UtilityCreateFault
2679 * XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string )
2681 * generates a struct containing a string member with id "faultString" and an int member
2682 * with id "faultCode". When using the xmlrpc xml serialization, these will be translated
2683 * to <fault><value><struct>... format.
2685 * fault_code application specific error code. can be 0.
2686 * fault_string application specific error string. cannot be null.
2688 * XMLRPC_VALUE a newly created struct vector representing the error, or null on error.
2690 * This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc
2691 * API or data structures. It is the author's view, that this API is intended for simple
2692 * data types, and a "fault" is a complex data type consisting of multiple simple data
2693 * types. This function is provided for convenience only, the same result could be
2694 * achieved directly by the application.
2696 * This function now supports some "standardized" fault codes, as specified at.
2697 * http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php.
2698 * If one of these fault codes is received, the description string will automatically
2699 * be prefixed with a standard error string and 2 newlines.
2701 * The actual transformation between this complex type and the xml "<fault>" element takes
2702 * place in the xmlrpc to xml serialization layer. This step is not performed when using the
2703 * simplerpc serialization, meaning that there will be no "<fault>" element in that
2704 * serialization. There will simply be a standard struct with 2 child elements.
2705 * imho, the "<fault>" element is unnecessary and/or out of place as part of the standard API.
2709 XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) {
2710 XMLRPC_VALUE xOutput = NULL;
2712 char* string = NULL;
2713 simplestring description;
2714 simplestring_init(&description);
2716 switch (fault_code) {
2717 case xmlrpc_error_parse_xml_syntax:
2718 string = xmlrpc_error_parse_xml_syntax_str;
2720 case xmlrpc_error_parse_unknown_encoding:
2721 string = xmlrpc_error_parse_unknown_encoding_str;
2723 case xmlrpc_error_parse_bad_encoding:
2724 string = xmlrpc_error_parse_bad_encoding_str;
2726 case xmlrpc_error_invalid_xmlrpc:
2727 string = xmlrpc_error_invalid_xmlrpc_str;
2729 case xmlrpc_error_unknown_method:
2730 string = xmlrpc_error_unknown_method_str;
2732 case xmlrpc_error_invalid_params:
2733 string = xmlrpc_error_invalid_params_str;
2735 case xmlrpc_error_internal_server:
2736 string = xmlrpc_error_internal_server_str;
2738 case xmlrpc_error_application:
2739 string = xmlrpc_error_application_str;
2741 case xmlrpc_error_system:
2742 string = xmlrpc_error_system_str;
2744 case xmlrpc_error_transport:
2745 string = xmlrpc_error_transport_str;
2749 simplestring_add(&description, string);
2751 if(string && fault_string) {
2752 simplestring_add(&description, "\n\n");
2754 simplestring_add(&description, fault_string);
2757 if(description.len) {
2758 xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
2760 XMLRPC_VectorAppendString (xOutput, "faultString", description.str,
2762 XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code);
2765 simplestring_free(&description);
2773 /****f* FAULT/XMLRPC_ValueIsFault
2775 * XMLRPC_ValueIsFault
2777 * int XMLRPC_ValueIsFault (XMLRPC_VALUE value)
2779 * Determines if a value encapsulates a fault "object"
2781 * value any XMLRPC_VALUE
2783 * 1 if it is a fault, else 0
2785 * XMLRPC_ResponseIsFault ()
2788 int XMLRPC_ValueIsFault (XMLRPC_VALUE value) {
2789 if( XMLRPC_VectorGetValueWithID(value, "faultCode") &&
2790 XMLRPC_VectorGetValueWithID(value, "faultString") ) {
2798 /****f* FAULT/XMLRPC_ResponseIsFault
2800 * XMLRPC_ResponseIsFault
2802 * int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response)
2804 * Determines if a response contains an encapsulated fault "object"
2806 * value any XMLRPC_REQUEST. typically of type xmlrpc_request_response
2808 * 1 if it contains a fault, else 0
2810 * XMLRPC_ValueIsFault ()
2813 int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) {
2814 return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) );
2819 /****f* FAULT/XMLRPC_GetValueFaultCode
2821 * XMLRPC_GetValueFaultCode
2823 * int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value)
2825 * returns fault code from a struct, if any
2827 * value XMLRPC_VALUE of type xmlrpc_vector_struct.
2829 * fault code, else 0.
2831 * impossible to distinguish faultCode == 0 from faultCode not present.
2833 * XMLRPC_GetResponseFaultCode ()
2836 int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) {
2837 return XMLRPC_VectorGetIntWithID(value, "faultCode");
2842 /****f* FAULT/XMLRPC_GetResponseFaultCode
2844 * XMLRPC_GetResponseFaultCode
2846 * int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response)
2848 * returns fault code from a response, if any
2850 * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2852 * fault code, else 0.
2854 * impossible to distinguish faultCode == 0 from faultCode not present.
2856 * XMLRPC_GetValueFaultCode ()
2859 int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) {
2860 return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) );
2866 /****f* FAULT/XMLRPC_GetValueFaultString
2868 * XMLRPC_GetValueFaultString
2870 * const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value)
2872 * returns fault string from a struct, if any
2874 * value XMLRPC_VALUE of type xmlrpc_vector_struct.
2876 * fault string, else 0.
2878 * XMLRPC_GetResponseFaultString ()
2881 const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) {
2882 return XMLRPC_VectorGetStringWithID(value, "faultString");
2887 /****f* FAULT/XMLRPC_GetResponseFaultString
2889 * XMLRPC_GetResponseFaultString
2891 * const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response)
2893 * returns fault string from a response, if any
2895 * response XMLRPC_REQUEST. typically of type xmlrpc_request_response.
2897 * fault string, else 0.
2899 * XMLRPC_GetValueFaultString ()
2902 const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) {
2903 return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) );
2909 /*-******************
2910 * Utility API funcs *
2911 ********************/
2914 /****f* UTILITY/XMLRPC_Free
2918 * void XMLRPC_Free(void* mem)
2920 * frees a block of memory allocated by xmlrpc.
2922 * mem memory to free
2926 * Useful for OS's where memory must be free'd
2927 * in the same library in which it is allocated.
2930 void XMLRPC_Free(void* mem) {
2937 /****f* UTILITY/XMLRPC_GetVersionString
2939 * XMLRPC_GetVersionString
2941 * const char* XMLRPC_GetVersionString()
2943 * returns library version string
2951 const char* XMLRPC_GetVersionString() {
2952 return XMLRPC_VERSION_STR;
2958 /*-**********************
2959 * End Utility API funcs *
2960 ************************/