X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=php%2Fxmlrpc%2Flibxmlrpc%2Fxmlrpc.c;fp=php%2Fxmlrpc%2Flibxmlrpc%2Fxmlrpc.c;h=0000000000000000000000000000000000000000;hb=e48b0945a0f03a51019f72399ac9f0eeabb90211;hp=d5f3f7b3f1b06a67c8bc5eaa0b45a8fc61168fee;hpb=f9ac2727e6fbddf97e885ffa1271a562315fb274;p=plcapi.git diff --git a/php/xmlrpc/libxmlrpc/xmlrpc.c b/php/xmlrpc/libxmlrpc/xmlrpc.c deleted file mode 100644 index d5f3f7b..0000000 --- a/php/xmlrpc/libxmlrpc/xmlrpc.c +++ /dev/null @@ -1,2963 +0,0 @@ -/* - This file is part of libXMLRPC - a C library for xml-encoded function calls. - - Author: Dan Libby (dan@libby.com) - Epinions.com may be contacted at feedback@epinions-inc.com -*/ - -/* - Copyright 2000 Epinions, Inc. - - Subject to the following 3 conditions, Epinions, Inc. permits you, free - of charge, to (a) use, copy, distribute, modify, perform and display this - software and associated documentation files (the "Software"), and (b) - permit others to whom the Software is furnished to do so as well. - - 1) The above copyright notice and this permission notice shall be included - without modification in all copies or substantial portions of the - Software. - - 2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF - ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY - IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE OR NONINFRINGEMENT. - - 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, - SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT - OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING - NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH - DAMAGES. - -*/ - - -static const char rcsid[] = "#(@) $Id$"; - - -/****h* ABOUT/xmlrpc - * NAME - * XMLRPC_VALUE - * AUTHOR - * Dan Libby, aka danda (dan@libby.com) - * CREATION DATE - * 9/1999 - 10/2000 - * HISTORY - * $Log: xmlrpc.c,v $ - * Revision 1.6 2004/04/27 17:33:59 iliaa - * Removed C++ style comments. - * - * Revision 1.5 2003/12/16 21:00:21 sniper - * Fix some compile warnings (patch by Joe Orton) - * - * Revision 1.4 2002/07/05 04:43:53 danda - * merged in updates from SF project. bring php repository up to date with xmlrpc-epi version 0.51 - * - * Revision 1.22 2002/03/09 23:15:44 danda - * add fault interrogation funcs - * - * Revision 1.21 2002/03/09 22:27:41 danda - * win32 build patches contributed by Jeff Lawson - * - * Revision 1.20 2002/02/13 20:58:50 danda - * patch to make source more windows friendly, contributed by Jeff Lawson - * - * Revision 1.19 2001/10/12 23:25:54 danda - * default to writing xmlrpc - * - * Revision 1.18 2001/09/29 21:58:05 danda - * adding cvs log to history section - * - * 10/15/2000 -- danda -- adding robodoc documentation - * 08/2000 -- danda -- PHP C extension that uses XMLRPC - * 08/2000 -- danda -- support for two vocabularies: danda-rpc and xml-rpc - * 09/1999 -- danda -- Initial API, before I even knew of standard XMLRPC vocab. Response only. - * 07/2000 -- danda -- wrote new implementation to be compatible with xmlrpc standard and - * incorporated some ideas from ensor, most notably the separation of - * xml dom from xmlrpc api. - * 06/2000 -- danda -- played with expat-ensor from www.ensor.org. Cool, but some flaws. - * TODO - * PORTABILITY - * Coded on RedHat Linux 6.2. Builds on Solaris x86. Should build on just - * about anything with minor mods. - * NOTES - * Welcome to XMLRPC. For more info on the specification and history, see - * http://www.xmlrpc.org. - * - * This code aims to be a full-featured C implementation of XMLRPC. It does not - * have any networking code. Rather, it is intended to be plugged into apps - * or libraries with existing networking facilities, eg PHP, apache, perl, mozilla, - * home-brew application servers, etc. - * - * Usage Paradigm: - * The user of this library will typically be implementing either an XMLRPC server, - * an XMLRPC client, or both. The client will use the library to build an in-memory - * representation of a request, and then serialize (encode) that request into XML. The - * client will then send the XML to the server via external mechanism. The server will - * de-serialize the XML back into an binary representation, call the appropriate registered - * method -- thereby generating a response. The response will be serialized into XML and - * sent back to the client. The client will de-serialize it into memory, and can - * iterate through the results via API. - * - * Both the request and the response may consist of arbitrarily long, arbitrarily nested - * values. The values may be one of several types, as defined by XMLRPC_VALUE_TYPE. - * - * Features and Architecture: - * - The XML parsing (xml_element.c) is completely independent of the XMLRPC api. In fact, - * it can be used as a standalone dom implementation. - * - Because of this, the same XMLRPC data can be serialized into multiple xml vocabularies. - * It is simply a matter of writing a transport. So far, two transports have been defined. - * The default xmlrpc vocab (xml_to_xmlrpc.c), and simple-rpc (xml_to_dandarpc.c) which is - * proprietary, but imho more readable, and nice for proprietary legacy reasons. - * - Various output options, including: xml escaping via CDATA or entity, case folding, - * vocab version, and character encoding. - * - One to One mapping between C structures and actual values, unlike ensor which forces - * one to understand the arcana of the xmlrpc vocab. - * - support for mixed indexed/keyed vector types, making it more compatible with - * languages such as PHP. - * - quite speedy compared to implementations written in interpreted languages. Also, uses - * intelligent string handling, so not many strlen() calls, etc. - * - comprehensive API for manipulation of values - *******/ - - -#ifdef _WIN32 -#include "xmlrpc_win32.h" -#endif -#include -#include -#include -#include -#include -#include - -#include "queue.h" -#include "xmlrpc.h" -#include "expat.h" -#include "base64.h" - -#include "xml_to_xmlrpc.h" -#include "xml_to_dandarpc.h" -#include "xml_to_soap.h" -#include "xml_element.h" -#include "xmlrpc_private.h" -#include "xmlrpc_introspection_private.h" -#include "system_methods_private.h" - - - -/*-********************* -* Begin Time Functions * -***********************/ - -static int date_from_ISO8601 (const char *text, time_t * value) { - struct tm tm; - int n; - int i; - char buf[18]; - - if (strchr (text, '-')) { - char *p = (char *) text, *p2 = buf; - while (p && *p) { - if (*p != '-') { - *p2 = *p; - p2++; - } - p++; - } - text = buf; - } - - - tm.tm_isdst = -1; - - if(strlen(text) < 17) { - return -1; - } - - n = 1000; - tm.tm_year = 0; - for(i = 0; i < 4; i++) { - tm.tm_year += (text[i]-'0')*n; - n /= 10; - } - n = 10; - tm.tm_mon = 0; - for(i = 0; i < 2; i++) { - tm.tm_mon += (text[i+4]-'0')*n; - n /= 10; - } - tm.tm_mon --; - - n = 10; - tm.tm_mday = 0; - for(i = 0; i < 2; i++) { - tm.tm_mday += (text[i+6]-'0')*n; - n /= 10; - } - - n = 10; - tm.tm_hour = 0; - for(i = 0; i < 2; i++) { - tm.tm_hour += (text[i+9]-'0')*n; - n /= 10; - } - - n = 10; - tm.tm_min = 0; - for(i = 0; i < 2; i++) { - tm.tm_min += (text[i+12]-'0')*n; - n /= 10; - } - - n = 10; - tm.tm_sec = 0; - for(i = 0; i < 2; i++) { - tm.tm_sec += (text[i+15]-'0')*n; - n /= 10; - } - - tm.tm_year -= 1900; - - *value = mktime(&tm); - - return 0; - -} - -static int date_to_ISO8601 (time_t value, char *buf, int length) { - struct tm *tm; - tm = localtime(&value); -#if 0 /* TODO: soap seems to favor this method. xmlrpc the latter. */ - return strftime (buf, length, "%Y-%m-%dT%H:%M:%SZ", tm); -#else - return strftime(buf, length, "%Y%m%dT%H:%M:%S", tm); -#endif -} - -/*-******************* -* End Time Functions * -*********************/ - - -/*-*************************** -* Begin XMLRPC_REQUEST funcs * -*****************************/ - -/****f* REQUEST/XMLRPC_RequestNew - * NAME - * XMLRPC_RequestNew - * SYNOPSIS - * XMLRPC_REQUEST XMLRPC_RequestNew() - * FUNCTION - * Creates a new XMLRPC_Request data struct - * INPUTS - * none - * SEE ALSO - * XMLRPC_RequestFree () - * SOURCE - */ -XMLRPC_REQUEST XMLRPC_RequestNew() { - XMLRPC_REQUEST xRequest = calloc(1, sizeof(STRUCT_XMLRPC_REQUEST)); - if(xRequest) { - simplestring_init(&xRequest->methodName); - } - return xRequest; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestFree - * NAME - * XMLRPC_RequestFree - * SYNOPSIS - * void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO) - * FUNCTION - * Free XMLRPC Request and all sub-values - * INPUTS - * request -- previously allocated request struct - * bFreeIO -- 1 = also free request value data, if any, 0 = ignore. - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_CleanupValue () - * SOURCE - */ -void XMLRPC_RequestFree(XMLRPC_REQUEST request, int bFreeIO) { - if(request) { - simplestring_free(&request->methodName); - - if(request->io && bFreeIO) { - XMLRPC_CleanupValue(request->io); - } - if(request->error) { - XMLRPC_CleanupValue(request->error); - } - my_free(request); - } -} - -/*******/ - -/* Set Method Name to call */ -/****f* REQUEST/XMLRPC_RequestSetMethodName - * NAME - * XMLRPC_RequestSetMethodName - * SYNOPSIS - * const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName) - * FUNCTION - * Set name of method to call with this request. - * INPUTS - * request -- previously allocated request struct - * methodName -- name of method - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestGetMethodName () - * XMLRPC_RequestFree () - * SOURCE - */ -const char* XMLRPC_RequestSetMethodName(XMLRPC_REQUEST request, const char* methodName) { - if(request) { - simplestring_clear(&request->methodName); - simplestring_add(&request->methodName, methodName); - return request->methodName.str; - } - return NULL; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestGetMethodName - * NAME - * XMLRPC_RequestGetMethodName - * SYNOPSIS - * const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request) - * FUNCTION - * Get name of method called by this request - * INPUTS - * request -- previously allocated request struct - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestSetMethodName () - * XMLRPC_RequestFree () - * SOURCE - */ -const char* XMLRPC_RequestGetMethodName(XMLRPC_REQUEST request) { - return request ? request->methodName.str : NULL; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestSetRequestType - * NAME - * XMLRPC_RequestSetRequestType - * SYNOPSIS - * XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType(XMLRPC_REQUEST request, XMLRPC_REQUEST_TYPE type) - * FUNCTION - * A request struct may be allocated by a caller or by xmlrpc - * in response to a request. This allows setting the - * request type. - * INPUTS - * request -- previously allocated request struct - * type -- request type [xmlrpc_method_call | xmlrpc_method_response] - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestGetRequestType () - * XMLRPC_RequestFree () - * XMLRPC_REQUEST_TYPE - * SOURCE - */ -XMLRPC_REQUEST_TYPE XMLRPC_RequestSetRequestType (XMLRPC_REQUEST request, - XMLRPC_REQUEST_TYPE type) { - if(request) { - request->request_type = type; - return request->request_type; - } - return xmlrpc_request_none; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestGetRequestType - * NAME - * XMLRPC_RequestGetRequestType - * SYNOPSIS - * XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request) - * FUNCTION - * A request struct may be allocated by a caller or by xmlrpc - * in response to a request. This allows setting the - * request type. - * INPUTS - * request -- previously allocated request struct - * RESULT - * type -- request type [xmlrpc_method_call | xmlrpc_method_response] - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestSetRequestType () - * XMLRPC_RequestFree () - * XMLRPC_REQUEST_TYPE - * SOURCE - */ -XMLRPC_REQUEST_TYPE XMLRPC_RequestGetRequestType(XMLRPC_REQUEST request) { - return request ? request->request_type : xmlrpc_request_none; -} - -/*******/ - - -/****f* REQUEST/XMLRPC_RequestSetData - * NAME - * XMLRPC_RequestSetData - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data) - * FUNCTION - * Associates a block of xmlrpc data with the request. The - * data is *not* copied. A pointer is kept. The caller - * should be careful not to doubly free the data value, - * which may optionally be free'd by XMLRPC_RequestFree(). - * INPUTS - * request -- previously allocated request struct - * data -- previously allocated data struct - * RESULT - * XMLRPC_VALUE -- pointer to value stored, or NULL - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestGetData () - * XMLRPC_RequestFree () - * XMLRPC_REQUEST - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_RequestSetData(XMLRPC_REQUEST request, XMLRPC_VALUE data) { - if(request && data) { - if (request->io) { - XMLRPC_CleanupValue (request->io); - } - request->io = XMLRPC_CopyValue(data); - return request->io; - } - return NULL; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestGetData - * NAME - * XMLRPC_RequestGetData - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request) - * FUNCTION - * Returns data associated with request, if any. - * INPUTS - * request -- previously allocated request struct - * RESULT - * XMLRPC_VALUE -- pointer to value stored, or NULL - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestSetData () - * XMLRPC_RequestFree () - * XMLRPC_REQUEST - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_RequestGetData(XMLRPC_REQUEST request) { - return request ? request->io : NULL; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestSetError - * NAME - * XMLRPC_RequestSetError - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_RequestSetError(XMLRPC_REQUEST request, XMLRPC_VALUE error) - * FUNCTION - * Associates a block of xmlrpc data, representing an error - * condition, with the request. - * INPUTS - * request -- previously allocated request struct - * error -- previously allocated error code or struct - * RESULT - * XMLRPC_VALUE -- pointer to value stored, or NULL - * NOTES - * This is a private function for usage by internals only. - * SEE ALSO - * XMLRPC_RequestGetError () - * SOURCE - */ -XMLRPC_VALUE XMLRPC_RequestSetError (XMLRPC_REQUEST request, XMLRPC_VALUE error) { - if (request && error) { - if (request->error) { - XMLRPC_CleanupValue (request->error); - } - request->error = XMLRPC_CopyValue (error); - return request->error; - } - return NULL; -} - -/*******/ - -/****f* REQUEST/XMLRPC_RequestGetError - * NAME - * XMLRPC_RequestGetError - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_RequestGetError(XMLRPC_REQUEST request) - * FUNCTION - * Returns error data associated with request, if any. - * INPUTS - * request -- previously allocated request struct - * RESULT - * XMLRPC_VALUE -- pointer to error value stored, or NULL - * NOTES - * This is a private function for usage by internals only. - * SEE ALSO - * XMLRPC_RequestSetError () - * XMLRPC_RequestFree () - * SOURCE - */ -XMLRPC_VALUE XMLRPC_RequestGetError (XMLRPC_REQUEST request) { - return request ? request->error : NULL; -} - -/*******/ - - -/****f* REQUEST/XMLRPC_RequestSetOutputOptions - * NAME - * XMLRPC_RequestSetOutputOptions - * SYNOPSIS - * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output) - * FUNCTION - * Sets output options used for generating XML. The output struct - * is copied, and may be freed by the caller. - * INPUTS - * request -- previously allocated request struct - * output -- output options struct initialized by caller - * RESULT - * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to value stored, or NULL - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestGetOutputOptions () - * XMLRPC_RequestFree () - * XMLRPC_REQUEST - * XMLRPC_REQUEST_OUTPUT_OPTIONS - * SOURCE - */ -XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestSetOutputOptions(XMLRPC_REQUEST request, XMLRPC_REQUEST_OUTPUT_OPTIONS output) { - if(request && output) { - memcpy (&request->output, output, - sizeof (STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS)); - return &request->output; - } - return NULL; -} - -/*******/ - - -/****f* REQUEST/XMLRPC_RequestGetOutputOptions - * NAME - * XMLRPC_RequestGetOutputOptions - * SYNOPSIS - * XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request) - * FUNCTION - * Gets a pointer to output options used for generating XML. - * INPUTS - * request -- previously allocated request struct - * RESULT - * XMLRPC_REQUEST_OUTPUT_OPTIONS -- pointer to options stored, or NULL - * SEE ALSO - * XMLRPC_RequestNew () - * XMLRPC_RequestSetOutputOptions () - * XMLRPC_RequestFree () - * XMLRPC_REQUEST - * XMLRPC_REQUEST_OUTPUT_OPTIONS - * SOURCE - */ -XMLRPC_REQUEST_OUTPUT_OPTIONS XMLRPC_RequestGetOutputOptions(XMLRPC_REQUEST request) { - return request ? &request->output : NULL; -} - -/*******/ - -/*-************************* -* End XMLRPC_REQUEST funcs * -***************************/ - - -/*-*************************** -* Begin Serializiation funcs * -*****************************/ - -/****f* SERIALIZE/XMLRPC_VALUE_ToXML - * NAME - * XMLRPC_VALUE_ToXML - * SYNOPSIS - * char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val) - * FUNCTION - * encode XMLRPC_VALUE into XML buffer. Note that the generated - * buffer will not contain a methodCall. - * INPUTS - * val -- previously allocated XMLRPC_VALUE - * buf_len -- length of returned buffer, if not null - * RESULT - * char* -- newly allocated buffer containing XML. - * It is the caller's responsibility to free it. - * SEE ALSO - * XMLRPC_REQUEST_ToXML () - * XMLRPC_VALUE_FromXML () - * XMLRPC_Free () - * XMLRPC_VALUE - * SOURCE - */ -char* XMLRPC_VALUE_ToXML(XMLRPC_VALUE val, int* buf_len) { - xml_element *root_elem = XMLRPC_VALUE_to_xml_element(val); - char* pRet = NULL; - - if(root_elem) { - pRet = xml_elem_serialize_to_string(root_elem, NULL, buf_len); - xml_elem_free(root_elem); - } - return pRet; -} - -/*******/ - -/****f* SERIALIZE/XMLRPC_REQUEST_ToXML - * NAME - * XMLRPC_REQUEST_ToXML - * SYNOPSIS - * char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request) - * FUNCTION - * encode XMLRPC_REQUEST into XML buffer - * INPUTS - * request -- previously allocated XMLRPC_REQUEST - * buf_len -- size of returned buf, if not null - * RESULT - * char* -- newly allocated buffer containing XML. - * It is the caller's responsibility to free it. - * SEE ALSO - * XMLRPC_REQUEST_ToXML () - * XMLRPC_REQUEST_FromXML () - * XMLRPC_Free () - * XMLRPC_VALUE_ToXML () - * XMLRPC_REQUEST - * SOURCE - */ -char* XMLRPC_REQUEST_ToXML(XMLRPC_REQUEST request, int* buf_len) { - char* pRet = NULL; - if (request) { - xml_element *root_elem = NULL; - if (request->output.version == xmlrpc_version_simple) { - root_elem = DANDARPC_REQUEST_to_xml_element (request); - } - else if (request->output.version == xmlrpc_version_1_0 || - request->output.version == xmlrpc_version_none) { - root_elem = XMLRPC_REQUEST_to_xml_element (request); - } - else if (request->output.version == xmlrpc_version_soap_1_1) { - root_elem = SOAP_REQUEST_to_xml_element (request); - } - - if(root_elem) { - pRet = - xml_elem_serialize_to_string (root_elem, - &request->output.xml_elem_opts, - buf_len); - xml_elem_free(root_elem); - } - } - return pRet; -} - -/*******/ - -/****f* SERIALIZE/XMLRPC_VALUE_FromXML - * NAME - * XMLRPC_VALUE_FromXML - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_VALUE_FromXML(const char* in_buf, int le - * FUNCTION - * Retrieve XMLRPC_VALUE from XML buffer. Note that this will - * ignore any methodCall. See XMLRPC_REQUEST_FromXML - * INPUTS - * in_buf -- character buffer containing XML - * len -- length of buffer - * RESULT - * XMLRPC_VALUE -- newly allocated data, or NULL if error. Should - * be free'd by caller. - * SEE ALSO - * XMLRPC_VALUE_ToXML () - * XMLRPC_REQUEST_FromXML () - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_VALUE_FromXML (const char *in_buf, int len, XMLRPC_REQUEST_INPUT_OPTIONS in_options) { - XMLRPC_VALUE xResponse = NULL; - XMLRPC_REQUEST req = XMLRPC_REQUEST_FromXML(in_buf, len, in_options); - - if(req) { - xResponse = req->io; - XMLRPC_RequestFree(req, 0); - } - return xResponse; -} - -/*******/ - -/* map parser errors to standard xml-rpc errors */ -static XMLRPC_VALUE map_expat_errors(XML_ELEM_ERROR error) { - XMLRPC_VALUE xReturn = NULL; - if(error) { - XMLRPC_ERROR_CODE code; - char buf[1024]; - snprintf(buf, sizeof(buf), - "error occurred at line %ld, column %ld, byte index %ld", - error->line, error->column, error->byte_index); - - /* expat specific errors */ - switch(error->parser_code) { - case XML_ERROR_UNKNOWN_ENCODING: - code = xmlrpc_error_parse_unknown_encoding; - break; - case XML_ERROR_INCORRECT_ENCODING: - code = xmlrpc_error_parse_bad_encoding; - break; - default: - code = xmlrpc_error_parse_xml_syntax; - break; - } - xReturn = XMLRPC_UtilityCreateFault(code, buf); - } - return xReturn; -} - -/****f* SERIALIZE/XMLRPC_REQUEST_FromXML - * NAME - * XMLRPC_REQUEST_FromXML - * SYNOPSIS - * XMLRPC_REQUEST XMLRPC_REQUEST_FromXML(const char* in_buf, int le - * FUNCTION - * Retrieve XMLRPC_REQUEST from XML buffer - * INPUTS - * in_buf -- character buffer containing XML - * len -- length of buffer - * RESULT - * XMLRPC_REQUEST -- newly allocated data, or NULL if error. Should - * be free'd by caller. - * SEE ALSO - * XMLRPC_REQUEST_ToXML () - * XMLRPC_VALUE_FromXML () - * XMLRPC_REQUEST - * SOURCE - */ -XMLRPC_REQUEST XMLRPC_REQUEST_FromXML (const char *in_buf, int len, - XMLRPC_REQUEST_INPUT_OPTIONS in_options) { - XMLRPC_REQUEST request = XMLRPC_RequestNew(); - STRUCT_XML_ELEM_ERROR error = {0}; - - if(request) { - xml_element *root_elem = - xml_elem_parse_buf (in_buf, len, - (in_options ? &in_options->xml_elem_opts : NULL), - &error); - - if(root_elem) { - if(!strcmp(root_elem->name, "simpleRPC")) { - request->output.version = xmlrpc_version_simple; - xml_element_to_DANDARPC_REQUEST(request, root_elem); - } - else if (!strcmp (root_elem->name, "SOAP-ENV:Envelope")) { - request->output.version = xmlrpc_version_soap_1_1; - xml_element_to_SOAP_REQUEST (request, root_elem); - } - else { - request->output.version = xmlrpc_version_1_0; - xml_element_to_XMLRPC_REQUEST(request, root_elem); - } - xml_elem_free(root_elem); - } - else { - if(error.parser_error) { - XMLRPC_RequestSetError (request, map_expat_errors (&error)); - } - } - } - - return request; -} - -/*******/ - -/*-************************ -* End Serialization Funcs * -**************************/ - - - -/****f* VALUE/XMLRPC_CreateValueEmpty - * NAME - * XMLRPC_CreateValueEmpty - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueEmpty () - * FUNCTION - * Create an XML value to be used/modified elsewhere. - * INPUTS - * RESULT - * XMLRPC_VALUE. The new value, or NULL on failure. - * SEE ALSO - * XMLRPC_CleanupValue () - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueEmpty() { - XMLRPC_VALUE v = calloc(1, sizeof(STRUCT_XMLRPC_VALUE)); - if(v) { -#ifdef XMLRPC_DEBUG_REFCOUNT - printf ("calloc'd 0x%x\n", v); -#endif - v->type = xmlrpc_empty; - simplestring_init(&v->id); - simplestring_init(&v->str); - } - return v; -} - -/*******/ - -/****f* VALUE/XMLRPC_SetValueID_Case - * NAME - * XMLRPC_SetValueID_Case - * SYNOPSIS - * const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case) - * FUNCTION - * Assign an ID (key) to an XMLRPC value. - * INPUTS - * value The xml value who's ID we will set. - * id The desired new id. - * len length of id string if known, or 0 if unknown. - * id_case one of XMLRPC_CASE - * RESULT - * const char* pointer to the newly allocated id string, or NULL - * SEE ALSO - * XMLRPC_SetValueID () - * XMLRPC_GetValueID () - * XMLRPC_VALUE - * XMLRPC_CASE - * SOURCE - */ -const char *XMLRPC_SetValueID_Case(XMLRPC_VALUE value, const char* id, int len, XMLRPC_CASE id_case) { - const char* pRetval = NULL; - if(value) { - if(id) { - simplestring_clear(&value->id); - (len > 0) ? simplestring_addn(&value->id, id, len) : - simplestring_add(&value->id, id); - - /* upper or lower case string in place if required. could be a seperate func. */ - if(id_case == xmlrpc_case_lower || id_case == xmlrpc_case_upper) { - int i; - for(i = 0; i < value->id.len; i++) { - value->id.str[i] = - (id_case == - xmlrpc_case_lower) ? tolower (value->id. - str[i]) : toupper (value-> - id. - str[i]); - } - } - - pRetval = value->id.str; - -#ifdef XMLRPC_DEBUG_REFCOUNT - printf("set value id: %s\n", pRetval); -#endif - } - } - - return pRetval; -} - -/*******/ - - -/****f* VALUE/XMLRPC_SetValueString - * NAME - * XMLRPC_SetValueString - * SYNOPSIS - * const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len) - * FUNCTION - * Assign a string value to an XMLRPC_VALUE, and set it to type xmlrpc_string - * INPUTS - * value The xml value who's ID we will set. - * val The desired new string val. - * len length of val string if known, or 0 if unknown. - * RESULT - * const char* pointer to the newly allocated value string, or NULL - * SEE ALSO - * XMLRPC_GetValueString () - * XMLRPC_VALUE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -const char *XMLRPC_SetValueString(XMLRPC_VALUE value, const char* val, int len) { - char *pRetval = NULL; - if(value && val) { - simplestring_clear(&value->str); - (len > 0) ? simplestring_addn(&value->str, val, len) : - simplestring_add(&value->str, val); - value->type = xmlrpc_string; - pRetval = (char *)value->str.str; - } - - return pRetval; -} - -/*******/ - -/****f* VALUE/XMLRPC_SetValueInt - * NAME - * XMLRPC_SetValueInt - * SYNOPSIS - * void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val) - * FUNCTION - * Assign an int value to an XMLRPC_VALUE, and set it to type xmlrpc_int - * INPUTS - * value The xml value who's ID we will set. - * val The desired new integer value - * RESULT - * SEE ALSO - * XMLRPC_GetValueInt () - * XMLRPC_VALUE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -void XMLRPC_SetValueInt(XMLRPC_VALUE value, int val) { - if(value) { - value->type = xmlrpc_int; - value->i = val; - } -} - -/*******/ - -/****f* VALUE/XMLRPC_SetValueBoolean - * NAME - * XMLRPC_SetValueBoolean - * SYNOPSIS - * void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val) - * FUNCTION - * Assign a boolean value to an XMLRPC_VALUE, and set it to type xmlrpc_boolean - * INPUTS - * value The xml value who's value we will set. - * val The desired new boolean value. [0 | 1] - * RESULT - * SEE ALSO - * XMLRPC_GetValueBoolean () - * XMLRPC_VALUE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -void XMLRPC_SetValueBoolean(XMLRPC_VALUE value, int val) { - if(value) { - value->type = xmlrpc_boolean; - value->i = val ? 1 : 0; - } -} - -/*******/ - - -/****f* VECTOR/XMLRPC_SetIsVector - * NAME - * XMLRPC_SetIsVector - * SYNOPSIS - * int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type) - * FUNCTION - * Set the XMLRPC_VALUE to be a vector (list) type. The vector may be one of - * [xmlrpc_array | xmlrpc_struct | xmlrpc_mixed]. An array has only index values. - * A struct has key/val pairs. Mixed allows both index and key/val combinations. - * INPUTS - * value The xml value who's vector type we will set - * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE - * RESULT - * int 1 if successful, 0 otherwise - * SEE ALSO - * XMLRPC_GetValueType () - * XMLRPC_GetVectorType () - * XMLRPC_VALUE - * XMLRPC_VECTOR_TYPE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -int XMLRPC_SetIsVector(XMLRPC_VALUE value, XMLRPC_VECTOR_TYPE type) { - int bSuccess = 0; - - if (value) { - /* we can change the type so long as nothing is currently stored. */ - if(value->type == xmlrpc_vector) { - if(value->v) { - if(!Q_Size(value->v->q)) { - value->v->type = type; - } - } - } - else { - value->v = calloc(1, sizeof(STRUCT_XMLRPC_VECTOR)); - if(value->v) { - value->v->q = (queue*)malloc(sizeof(queue)); - if(value->v->q) { - Q_Init(value->v->q); - value->v->type = type; - value->type = xmlrpc_vector; - bSuccess = 1; - } - } - } - } - - return bSuccess; -} - -/*******/ - -/****f* VECTOR/XMLRPC_CreateVector - * NAME - * XMLRPC_CreateVector - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type) - * FUNCTION - * Create a new vector and optionally set an id. - * INPUTS - * id The id of the vector, or NULL - * type New type of vector as enumerated by XMLRPC_VECTOR_TYPE - * RESULT - * XMLRPC_VALUE The new vector, or NULL on failure. - * SEE ALSO - * XMLRPC_CreateValueEmpty () - * XMLRPC_SetIsVector () - * XMLRPC_GetValueType () - * XMLRPC_GetVectorType () - * XMLRPC_VALUE - * XMLRPC_VECTOR_TYPE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateVector(const char* id, XMLRPC_VECTOR_TYPE type) { - XMLRPC_VALUE val = NULL; - - val = XMLRPC_CreateValueEmpty(); - if(val) { - if(XMLRPC_SetIsVector(val, type)) { - if(id) { - const char *pSVI = NULL; - - pSVI = XMLRPC_SetValueID(val, id, 0); - if(NULL == pSVI) { - val = NULL; - } - } - } - else { - val = NULL; - } - } - return val; -} - -/*******/ - - -/* Not yet implemented. - * - * This should use a hash to determine if a given target id has already - * been appended. - * - * Alternately, it could walk the entire vector, but that could be quite - * slow for very large lists. - */ -static int isDuplicateEntry(XMLRPC_VALUE target, XMLRPC_VALUE source) { - return 0; -} - -/****f* VECTOR/XMLRPC_AddValueToVector - * NAME - * XMLRPC_AddValueToVector - * SYNOPSIS - * int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source) - * FUNCTION - * Add (append) an existing XMLRPC_VALUE to a vector. - * INPUTS - * target The target vector - * source The source value to append - * RESULT - * int 1 if successful, else 0 - * SEE ALSO - * XMLRPC_AddValuesToVector () - * XMLRPC_VectorGetValueWithID_Case () - * XMLRPC_VALUE - * NOTES - * The function will fail and return 0 if an attempt is made to add - * a value with an ID into a vector of type xmlrpc_vector_array. Such - * values can only be added to xmlrpc_vector_struct. - * SOURCE - */ -int XMLRPC_AddValueToVector(XMLRPC_VALUE target, XMLRPC_VALUE source) { - if(target && source) { - if(target->type == xmlrpc_vector && target->v && - target->v->q && target->v->type != xmlrpc_vector_none) { - - /* guard against putting value of unknown type into vector */ - switch(source->type) { - case xmlrpc_empty: - case xmlrpc_nil: - case xmlrpc_base64: - case xmlrpc_boolean: - case xmlrpc_datetime: - case xmlrpc_double: - case xmlrpc_int: - case xmlrpc_string: - case xmlrpc_vector: - /* Guard against putting a key/val pair into an array vector */ - if( !(source->id.len && target->v->type == xmlrpc_vector_array) ) { - if (isDuplicateEntry (target, source) - || Q_PushTail (target->v->q, XMLRPC_CopyValue (source))) { - return 1; - } - } - else { - fprintf (stderr, - "xmlrpc: attempted to add key/val pair to vector of type array\n"); - } - break; - default: - fprintf (stderr, - "xmlrpc: attempted to add value of unknown type to vector\n"); - break; - } - } - } - return 0; -} - -/*******/ - - -/****f* VECTOR/XMLRPC_AddValuesToVector - * NAME - * XMLRPC_AddValuesToVector - * SYNOPSIS - * XMLRPC_AddValuesToVector ( target, val1, val2, val3, val(n), 0 ) - * XMLRPC_AddValuesToVector( XMLRPC_VALUE, ... ) - * FUNCTION - * Add (append) a series of existing XMLRPC_VALUE to a vector. - * INPUTS - * target The target vector - * ... The source value(s) to append. The last item *must* be 0. - * RESULT - * int 1 if successful, else 0 - * SEE ALSO - * XMLRPC_AddValuesToVector () - * XMLRPC_VectorGetValueWithID_Case () - * XMLRPC_VALUE - * NOTES - * This function may actually return failure after it has already modified - * or added items to target. You can not trust the state of target - * if this function returns failure. - * SOURCE - */ -int XMLRPC_AddValuesToVector(XMLRPC_VALUE target, ...) { - int iRetval = 0; - - if(target) { - if(target->type == xmlrpc_vector) { - XMLRPC_VALUE v = NULL; - va_list vl; - - va_start(vl, target); - - do { - v = va_arg(vl, XMLRPC_VALUE); - if(v) { - if(!XMLRPC_AddValueToVector(target, v)) { - iRetval = 0; - break; - } - } - } - while (v); - - va_end(vl); - - if(NULL == v) { - iRetval = 1; - } - } - } - return iRetval; -} - -/*******/ - - -/****f* VECTOR/XMLRPC_VectorGetValueWithID_Case - * NAME - * XMLRPC_VectorGetValueWithID_Case - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case(XMLRPC_VALUE vector, const char* id, XMLRPC_CASE_COMPARISON id_case) - * FUNCTION - * Get value from vector matching id (key) - * INPUTS - * vector The source vector - * id The key to find - * id_case Rule for how to match key - * RESULT - * int 1 if successful, else 0 - * SEE ALSO - * XMLRPC_SetValueID_Case () - * XMLRPC_VALUE - * XMLRPC_CASE_COMPARISON - * SOURCE - */ -XMLRPC_VALUE XMLRPC_VectorGetValueWithID_Case (XMLRPC_VALUE vector, const char *id, - XMLRPC_CASE_COMPARISON id_case) { - if(vector && vector->v && vector->v->q) { - q_iter qi = Q_Iter_Head_F(vector->v->q); - - while(qi) { - XMLRPC_VALUE xIter = Q_Iter_Get_F(qi); - if(xIter && xIter->id.str) { - if(id_case == xmlrpc_case_sensitive) { - if(!strcmp(xIter->id.str, id)) { - return xIter; - } - } - else if(id_case == xmlrpc_case_insensitive) { - if(!strcasecmp(xIter->id.str, id)) { - return xIter; - } - } - } - qi = Q_Iter_Next_F(qi); - } - } - return NULL; -} - -/*******/ - - -int XMLRPC_VectorRemoveValue(XMLRPC_VALUE vector, XMLRPC_VALUE value) { - if(vector && vector->v && vector->v->q && value) { - q_iter qi = Q_Iter_Head_F(vector->v->q); - - while(qi) { - XMLRPC_VALUE xIter = Q_Iter_Get_F(qi); - if(xIter == value) { - XMLRPC_CleanupValue(xIter); - Q_Iter_Del(vector->v->q, qi); - return 1; - } - qi = Q_Iter_Next_F(qi); - } - } - return 0; -} - - -/****f* VALUE/XMLRPC_CreateValueString - * NAME - * XMLRPC_CreateValueString - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) - * FUNCTION - * Create an XMLRPC_VALUE, and assign a string to it - * INPUTS - * id The id of the value, or NULL - * val The desired new string val. - * len length of val string if known, or 0 if unknown. - * RESULT - * newly allocated XMLRPC_VALUE, or NULL - * SEE ALSO - * XMLRPC_GetValueString () - * XMLRPC_CreateValueEmpty () - * XMLRPC_VALUE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueString(const char* id, const char* val, int len) { - XMLRPC_VALUE value = NULL; - if(val) { - value = XMLRPC_CreateValueEmpty(); - if(value) { - XMLRPC_SetValueString(value, val, len); - if(id) { - XMLRPC_SetValueID(value, id, 0); - } - } - } - return value; -} - -/*******/ - -/****f* VALUE/XMLRPC_CreateValueInt - * NAME - * XMLRPC_CreateValueInt - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) - * FUNCTION - * Create an XMLRPC_VALUE, and assign an int to it - * INPUTS - * id The id of the value, or NULL - * i The desired new int val. - * RESULT - * newly allocated XMLRPC_VALUE, or NULL - * SEE ALSO - * XMLRPC_GetValueInt () - * XMLRPC_CreateValueEmpty () - * XMLRPC_VALUE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueInt(const char* id, int i) { - XMLRPC_VALUE val = XMLRPC_CreateValueEmpty(); - if(val) { - XMLRPC_SetValueInt(val, i); - if(id) { - XMLRPC_SetValueID(val, id, 0); - } - } - return val; -} - -/*******/ - -/****f* VALUE/XMLRPC_CreateValueBoolean - * NAME - * XMLRPC_CreateValueBoolean - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) - * FUNCTION - * Create an XMLRPC_VALUE, and assign an int to it - * INPUTS - * id The id of the value, or NULL - * i The desired new int val. - * RESULT - * newly allocated XMLRPC_VALUE, or NULL - * SEE ALSO - * XMLRPC_GetValueBoolean () - * XMLRPC_CreateValueEmpty () - * XMLRPC_VALUE - * XMLRPC_VALUE_TYPE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueBoolean(const char* id, int i) { - XMLRPC_VALUE val = XMLRPC_CreateValueEmpty(); - if(val) { - XMLRPC_SetValueBoolean(val, i); - if(id) { - XMLRPC_SetValueID(val, id, 0); - } - } - return val; -} - -/*******/ - - -/****f* VALUE/XMLRPC_CleanupValue - * NAME - * XMLRPC_CleanupValue - * SYNOPSIS - * void XMLRPC_CleanupValue(XMLRPC_VALUE value) - * FUNCTION - * Frees all memory allocated for an XMLRPC_VALUE and any of its children (if a vector) - * INPUTS - * value The id of the value to be cleaned up. - * RESULT - * void - * NOTES - * Normally this function will be called for the topmost vector, thus free-ing - * all children. If a child of a vector is free'd first, results are undefined. - * Failure to call this function *will* cause memory leaks. - * - * Also, this function is implemented using reference counting. Thus a value - * may be added and freed from multiple parents so long as a reference is added - * first using XMLRPC_CopyValue() - * SEE ALSO - * XMLRPC_RequestFree () - * XMLRPC_CreateValueEmpty () - * XMLRPC_CopyValue() - * XMLRPC_VALUE - * SOURCE - */ -void XMLRPC_CleanupValue(XMLRPC_VALUE value) { - if(value) { - if(value->iRefCount > 0) { - value->iRefCount --; - } - -#ifdef XMLRPC_DEBUG_REFCOUNT - if(value->id.str) { - printf ("decremented refcount of %s, now %i\n", value->id.str, - value->iRefCount); - } - else { - printf ("decremented refcount of 0x%x, now %i\n", value, - value->iRefCount); - } -#endif - - if(value->type == xmlrpc_vector) { - if(value->v) { - if(value->iRefCount == 0) { - XMLRPC_VALUE cur = (XMLRPC_VALUE)Q_Head(value->v->q); - while( cur ) { - XMLRPC_CleanupValue(cur); - - /* Make sure some idiot didn't include a vector as a child of itself - * and thus it would have already free'd these. - */ - if(value->v && value->v->q) { - cur = Q_Next(value->v->q); - } - else { - break; - } - } - - Q_Destroy(value->v->q); - my_free(value->v->q); - my_free(value->v); - } - } - } - - - if(value->iRefCount == 0) { - - /* guard against freeing invalid types */ - switch(value->type) { - case xmlrpc_empty: - case xmlrpc_base64: - case xmlrpc_boolean: - case xmlrpc_datetime: - case xmlrpc_double: - case xmlrpc_int: - case xmlrpc_string: - case xmlrpc_vector: -#ifdef XMLRPC_DEBUG_REFCOUNT - if(value->id.str) { - printf("free'd %s\n", value->id.str); - } - else { - printf("free'd 0x%x\n", value); - } -#endif - simplestring_free(&value->id); - simplestring_free(&value->str); - - memset(value, 0, sizeof(STRUCT_XMLRPC_VALUE)); - my_free(value); - break; - default: - fprintf (stderr, - "xmlrpc: attempted to free value of invalid type\n"); - break; - } - } - } -} - -/*******/ - - -/****f* VALUE/XMLRPC_SetValueDateTime - * NAME - * XMLRPC_SetValueDateTime - * SYNOPSIS - * void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) - * FUNCTION - * Assign time value to XMLRPC_VALUE - * INPUTS - * value The target XMLRPC_VALUE - * time The desired new unix time value (time_t) - * RESULT - * void - * SEE ALSO - * XMLRPC_GetValueDateTime () - * XMLRPC_SetValueDateTime_ISO8601 () - * XMLRPC_CreateValueDateTime () - * XMLRPC_VALUE - * SOURCE - */ -void XMLRPC_SetValueDateTime(XMLRPC_VALUE value, time_t time) { - if(value) { - char timeBuf[30]; - value->type = xmlrpc_datetime; - value->i = time; - - timeBuf[0] = 0; - - date_to_ISO8601(time, timeBuf, sizeof(timeBuf)); - - if(timeBuf[0]) { - simplestring_clear(&value->str); - simplestring_add(&value->str, timeBuf); - } - } -} - -/*******/ - -/****f* VALUE/XMLRPC_CopyValue - * NAME - * XMLRPC_CopyValue - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) - * FUNCTION - * Make a copy (reference) of an XMLRPC_VALUE - * INPUTS - * value The target XMLRPC_VALUE - * RESULT - * XMLRPC_VALUE -- address of the copy - * SEE ALSO - * XMLRPC_CleanupValue () - * XMLRPC_DupValueNew () - * NOTES - * This function is implemented via reference counting, so the - * returned value is going to be the same as the passed in value. - * The value must be freed the same number of times it is copied - * or there will be a memory leak. - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CopyValue(XMLRPC_VALUE value) { - if(value) { - value->iRefCount ++; -#ifdef XMLRPC_DEBUG_REFCOUNT - if(value->id.str) { - printf ("incremented refcount of %s, now %i\n", value->id.str, - value->iRefCount); - } - else { - printf ("incremented refcount of 0x%x, now %i\n", value, - value->iRefCount); - } -#endif - } - return value; -} - -/*******/ - - -/****f* VALUE/XMLRPC_DupValueNew - * NAME - * XMLRPC_DupValueNew - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_DupValueNew(XMLRPC_VALUE value) - * FUNCTION - * Make a duplicate (non reference) of an XMLRPC_VALUE with newly allocated mem. - * INPUTS - * value The source XMLRPC_VALUE to duplicate - * RESULT - * XMLRPC_VALUE -- address of the duplicate value - * SEE ALSO - * XMLRPC_CleanupValue () - * XMLRPC_CopyValue () - * NOTES - * Use this when function when you need to modify the contents of - * the copied value seperately from the original. - * - * this function is recursive, thus the value and all of its children - * (if any) will be duplicated. - * SOURCE - */ -XMLRPC_VALUE XMLRPC_DupValueNew (XMLRPC_VALUE xSource) { - XMLRPC_VALUE xReturn = NULL; - if (xSource) { - xReturn = XMLRPC_CreateValueEmpty (); - if (xSource->id.len) { - XMLRPC_SetValueID (xReturn, xSource->id.str, xSource->id.len); - } - - switch (xSource->type) { - case xmlrpc_int: - case xmlrpc_boolean: - XMLRPC_SetValueInt (xReturn, xSource->i); - break; - case xmlrpc_string: - case xmlrpc_base64: - XMLRPC_SetValueString (xReturn, xSource->str.str, xSource->str.len); - break; - case xmlrpc_datetime: - XMLRPC_SetValueDateTime (xReturn, xSource->i); - break; - case xmlrpc_double: - XMLRPC_SetValueDouble (xReturn, xSource->d); - break; - case xmlrpc_vector: - { - q_iter qi = Q_Iter_Head_F (xSource->v->q); - XMLRPC_SetIsVector (xReturn, xSource->v->type); - - while (qi) { - XMLRPC_VALUE xIter = Q_Iter_Get_F (qi); - XMLRPC_AddValueToVector (xReturn, XMLRPC_DupValueNew (xIter)); - qi = Q_Iter_Next_F (qi); - } - } - break; - default: - break; - } - } - return xReturn; -} - -/*******/ - - - -/****f* VALUE/XMLRPC_CreateValueDateTime - * NAME - * XMLRPC_CreateValueDateTime - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) - * FUNCTION - * Create new datetime value from time_t - * INPUTS - * id id of the new value, or NULL - * time The desired unix time value (time_t) - * RESULT - * void - * SEE ALSO - * XMLRPC_GetValueDateTime () - * XMLRPC_SetValueDateTime () - * XMLRPC_CreateValueDateTime_ISO8601 () - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueDateTime(const char* id, time_t time) { - XMLRPC_VALUE val = XMLRPC_CreateValueEmpty(); - if(val) { - XMLRPC_SetValueDateTime(val, time); - if(id) { - XMLRPC_SetValueID(val, id, 0); - } - } - return val; -} - -/*******/ - - -/****f* VALUE/XMLRPC_SetValueDateTime_ISO8601 - * NAME - * XMLRPC_SetValueDateTime_ISO8601 - * SYNOPSIS - * void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) - * FUNCTION - * Set datetime value from IS08601 encoded string - * INPUTS - * value The target XMLRPC_VALUE - * s The desired new time value - * RESULT - * void - * BUGS - * This function currently attempts to convert the time string to a valid unix time - * value before passing it. Behavior when the string is invalid or out of range - * is not well defined, but will probably result in Jan 1, 1970 (0) being passed. - * SEE ALSO - * XMLRPC_GetValueDateTime_ISO8601 () - * XMLRPC_CreateValueDateTime_ISO8601 () - * XMLRPC_CreateValueDateTime () - * XMLRPC_VALUE - * SOURCE - */ -void XMLRPC_SetValueDateTime_ISO8601(XMLRPC_VALUE value, const char* s) { - if(value) { - time_t time_val = 0; - if(s) { - date_from_ISO8601(s, &time_val); - XMLRPC_SetValueDateTime(value, time_val); - } - } -} - -/*******/ - -/****f* VALUE/XMLRPC_CreateValueDateTime_ISO8601 - * NAME - * XMLRPC_CreateValueDateTime_ISO8601 - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) - * FUNCTION - * Create datetime value from IS08601 encoded string - * INPUTS - * id The id of the new value, or NULL - * s The desired new time value - * RESULT - * newly allocated XMLRPC_VALUE, or NULL if no value created. - * BUGS - * See XMLRPC_SetValueDateTime_ISO8601 () - * SEE ALSO - * XMLRPC_GetValueDateTime_ISO8601 () - * XMLRPC_SetValueDateTime_ISO8601 () - * XMLRPC_CreateValueDateTime () - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueDateTime_ISO8601(const char* id, const char *s) { - XMLRPC_VALUE val = XMLRPC_CreateValueEmpty(); - if(val) { - XMLRPC_SetValueDateTime_ISO8601(val, s); - if(id) { - XMLRPC_SetValueID(val, id, 0); - } - } - return val; -} - -/*******/ - - -/****f* VALUE/XMLRPC_SetValueBase64 - * NAME - * XMLRPC_SetValueBase64 - * SYNOPSIS - * void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) - * FUNCTION - * Set base64 value. Base64 is useful for transferring binary data, such as an image. - * INPUTS - * value The target XMLRPC_VALUE - * s The desired new binary value - * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed. - * RESULT - * void - * NOTES - * Data is set/stored/retrieved as passed in, but is base64 encoded for XML transfer, and - * decoded on the other side. This is transparent to the caller. - * SEE ALSO - * XMLRPC_GetValueBase64 () - * XMLRPC_CreateValueBase64 () - * XMLRPC_VALUE - * SOURCE - */ -void XMLRPC_SetValueBase64(XMLRPC_VALUE value, const char* s, int len) { - if(value && s) { - simplestring_clear(&value->str); - (len > 0) ? simplestring_addn(&value->str, s, len) : - simplestring_add(&value->str, s); - value->type = xmlrpc_base64; - } -} - -/*******/ - - -/****f* VALUE/XMLRPC_CreateValueBase64 - * NAME - * XMLRPC_CreateValueBase64 - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) - * FUNCTION - * Create base64 value. Base64 is useful for transferring binary data, such as an image. - * INPUTS - * id id of the new value, or NULL - * s The desired new binary value - * len The length of s, or NULL. If buffer is not null terminated, len *must* be passed. - * RESULT - * newly allocated XMLRPC_VALUE, or NULL if error - * NOTES - * See XMLRPC_SetValueBase64 () - * SEE ALSO - * XMLRPC_GetValueBase64 () - * XMLRPC_SetValueBase64 () - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueBase64(const char* id, const char* s, int len) { - XMLRPC_VALUE val = XMLRPC_CreateValueEmpty(); - if(val) { - XMLRPC_SetValueBase64(val, s, len); - if(id) { - XMLRPC_SetValueID(val, id, 0); - } - } - return val; -} - -/*******/ - -/****f* VALUE/XMLRPC_SetValueDouble - * NAME - * XMLRPC_SetValueDouble - * SYNOPSIS - * void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) - * FUNCTION - * Set double (floating point) value. - * INPUTS - * value The target XMLRPC_VALUE - * val The desired new double value - * RESULT - * void - * SEE ALSO - * XMLRPC_GetValueDouble () - * XMLRPC_CreateValueDouble () - * XMLRPC_VALUE - * SOURCE - */ -void XMLRPC_SetValueDouble(XMLRPC_VALUE value, double val) { - if(value) { - value->type = xmlrpc_double; - value->d = val; - } -} - -/*******/ - -/****f* VALUE/XMLRPC_CreateValueDouble - * NAME - * XMLRPC_CreateValueDouble - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) - * FUNCTION - * Create double (floating point) value. - * INPUTS - * id id of the newly created value, or NULL - * d The desired new double value - * RESULT - * void - * SEE ALSO - * XMLRPC_GetValueDouble () - * XMLRPC_CreateValueDouble () - * XMLRPC_VALUE - * SOURCE - */ -XMLRPC_VALUE XMLRPC_CreateValueDouble(const char* id, double d) { - XMLRPC_VALUE val = XMLRPC_CreateValueEmpty(); - if(val) { - XMLRPC_SetValueDouble(val, d); - if(id) { - XMLRPC_SetValueID(val, id, 0); - } - } - return val; -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueString - * NAME - * XMLRPC_GetValueString - * SYNOPSIS - * const char* XMLRPC_GetValueString(XMLRPC_VALUE value) - * FUNCTION - * retrieve string value - * INPUTS - * value source XMLRPC_VALUE of type xmlrpc_string - * RESULT - * void - * SEE ALSO - * XMLRPC_SetValueString () - * XMLRPC_GetValueType () - * XMLRPC_VALUE - * SOURCE - */ -const char* XMLRPC_GetValueString(XMLRPC_VALUE value) { - return ((value && value->type == xmlrpc_string) ? value->str.str : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueStringLen - * NAME - * XMLRPC_GetValueStringLen - * SYNOPSIS - * int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) - * FUNCTION - * determine length of string value - * INPUTS - * value XMLRPC_VALUE of type xmlrpc_string - * RESULT - * length of string, or 0 - * NOTES - * SEE ALSO - * XMLRPC_SetValueString () - * XMLRPC_GetValueString () - * SOURCE - */ -int XMLRPC_GetValueStringLen(XMLRPC_VALUE value) { - return ((value) ? value->str.len : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueInt - * NAME - * XMLRPC_GetValueInt - * SYNOPSIS - * int XMLRPC_GetValueInt(XMLRPC_VALUE value) - * FUNCTION - * retrieve integer value. - * INPUTS - * value XMLRPC_VALUE of type xmlrpc_int - * RESULT - * integer value or 0 if value is not valid int - * NOTES - * use XMLRPC_GetValueType () to be sure if 0 is real return value or not - * SEE ALSO - * XMLRPC_SetValueInt () - * XMLRPC_CreateValueInt () - * SOURCE - */ -int XMLRPC_GetValueInt(XMLRPC_VALUE value) { - return ((value && value->type == xmlrpc_int) ? value->i : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueBoolean - * NAME - * XMLRPC_GetValueBoolean - * SYNOPSIS - * int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) - * FUNCTION - * retrieve boolean value. - * INPUTS - * XMLRPC_VALUE of type xmlrpc_boolean - * RESULT - * boolean value or 0 if value is not valid boolean - * NOTES - * use XMLRPC_GetValueType() to be sure if 0 is real value or not - * SEE ALSO - * XMLRPC_SetValueBoolean () - * XMLRPC_CreateValueBoolean () - * SOURCE - */ -int XMLRPC_GetValueBoolean(XMLRPC_VALUE value) { - return ((value && value->type == xmlrpc_boolean) ? value->i : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueDouble - * NAME - * XMLRPC_GetValueDouble - * SYNOPSIS - * double XMLRPC_GetValueDouble(XMLRPC_VALUE value) - * FUNCTION - * retrieve double value - * INPUTS - * XMLRPC_VALUE of type xmlrpc_double - * RESULT - * double value or 0 if value is not valid double. - * NOTES - * use XMLRPC_GetValueType() to be sure if 0 is real value or not - * SEE ALSO - * XMLRPC_SetValueDouble () - * XMLRPC_CreateValueDouble () - * SOURCE - */ -double XMLRPC_GetValueDouble(XMLRPC_VALUE value) { - return ((value && value->type == xmlrpc_double) ? value->d : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueBase64 - * NAME - * XMLRPC_GetValueBase64 - * SYNOPSIS - * const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) - * FUNCTION - * retrieve binary value - * INPUTS - * XMLRPC_VALUE of type xmlrpc_base64 - * RESULT - * pointer to binary value or 0 if value is not valid. - * SEE ALSO - * XMLRPC_SetValueBase64 () - * XMLRPC_CreateValueBase64 () - * NOTES - * Call XMLRPC_GetValueStringLen() to retrieve real length of binary data. strlen() - * will not be accurate, as returned data may contain embedded nulls. - * SOURCE - */ -const char* XMLRPC_GetValueBase64(XMLRPC_VALUE value) { - return ((value && value->type == xmlrpc_base64) ? value->str.str : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueDateTime - * NAME - * XMLRPC_GetValueDateTime - * SYNOPSIS - * time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) - * FUNCTION - * retrieve time_t value - * INPUTS - * XMLRPC_VALUE of type xmlrpc_datetime - * RESULT - * time_t value or 0 if value is not valid datetime. - * NOTES - * use XMLRPC_GetValueType() to be sure if 0 is real value or not - * SEE ALSO - * XMLRPC_SetValueDateTime () - * XMLRPC_GetValueDateTime_ISO8601 () - * XMLRPC_CreateValueDateTime () - * SOURCE - */ -time_t XMLRPC_GetValueDateTime(XMLRPC_VALUE value) { - return (time_t)((value && value->type == xmlrpc_datetime) ? value->i : 0); -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueDateTime_IOS8601 - * NAME - * XMLRPC_GetValueDateTime_IOS8601 - * SYNOPSIS - * const char* XMLRPC_GetValueDateTime_IOS8601(XMLRPC_VALUE value) - * FUNCTION - * retrieve ISO8601 formatted time value - * INPUTS - * XMLRPC_VALUE of type xmlrpc_datetime - * RESULT - * const char* value or 0 if value is not valid datetime. - * SEE ALSO - * XMLRPC_SetValueDateTime_IOS8601 () - * XMLRPC_GetValueDateTime () - * XMLRPC_CreateValueDateTime_IOS8601 () - * SOURCE - */ -const char* XMLRPC_GetValueDateTime_ISO8601(XMLRPC_VALUE value) { - return ((value && value->type == xmlrpc_datetime) ? value->str.str : 0); -} - -/*******/ - -/* Get ID (key) of value or NULL */ -/****f* VALUE/XMLRPC_GetValueID - * NAME - * XMLRPC_GetValueID - * SYNOPSIS - * const char* XMLRPC_GetValueID(XMLRPC_VALUE value) - * FUNCTION - * retrieve id (key) of value - * INPUTS - * XMLRPC_VALUE of any type - * RESULT - * const char* pointer to id of value, or NULL - * NOTES - * SEE ALSO - * XMLRPC_SetValueID() - * XMLRPC_CreateValueEmpty() - * SOURCE - */ -const char* XMLRPC_GetValueID(XMLRPC_VALUE value) { - return (const char*)((value && value->id.len) ? value->id.str : 0); -} - -/*******/ - - -/****f* VECTOR/XMLRPC_VectorSize - * NAME - * XMLRPC_VectorSize - * SYNOPSIS - * int XMLRPC_VectorSize(XMLRPC_VALUE value) - * FUNCTION - * retrieve size of vector - * INPUTS - * XMLRPC_VALUE of type xmlrpc_vector - * RESULT - * count of items in vector - * NOTES - * This is a cheap operation even on large vectors. Vector size is - * maintained by queue during add/remove ops. - * SEE ALSO - * XMLRPC_AddValueToVector () - * SOURCE - */ -int XMLRPC_VectorSize(XMLRPC_VALUE value) { - int size = 0; - if(value && value->type == xmlrpc_vector && value->v) { - size = Q_Size(value->v->q); - } - return size; -} - -/*******/ - -/****f* VECTOR/XMLRPC_VectorRewind - * NAME - * XMLRPC_VectorRewind - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) - * FUNCTION - * reset vector to first item - * INPUTS - * XMLRPC_VALUE of type xmlrpc_vector - * RESULT - * first XMLRPC_VALUE in list, or NULL if empty or error. - * NOTES - * Be careful to rewind any vector passed in to you if you expect to - * iterate through the entire list. - * SEE ALSO - * XMLRPC_VectorNext () - * SOURCE - */ -XMLRPC_VALUE XMLRPC_VectorRewind(XMLRPC_VALUE value) { - XMLRPC_VALUE xReturn = NULL; - if(value && value->type == xmlrpc_vector && value->v) { - xReturn = (XMLRPC_VALUE)Q_Head(value->v->q); - } - return xReturn; -} - -/*******/ - -/****f* VECTOR/XMLRPC_VectorNext - * NAME - * XMLRPC_VectorNext - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) - * FUNCTION - * Iterate vector to next item in list. - * INPUTS - * XMLRPC_VALUE of type xmlrpc_vector - * RESULT - * Next XMLRPC_VALUE in vector, or NULL if at end. - * NOTES - * SEE ALSO - * XMLRPC_VectorRewind () - * SOURCE - */ -XMLRPC_VALUE XMLRPC_VectorNext(XMLRPC_VALUE value) { - XMLRPC_VALUE xReturn = NULL; - if(value && value->type == xmlrpc_vector && value->v) { - xReturn = (XMLRPC_VALUE)Q_Next(value->v->q); - } - return xReturn; -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueType - * NAME - * XMLRPC_GetValueType - * SYNOPSIS - * XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) - * FUNCTION - * determine data type of the XMLRPC_VALUE - * INPUTS - * XMLRPC_VALUE target of query - * RESULT - * data type of value as enumerated by XMLRPC_VALUE_TYPE - * NOTES - * all values are of type xmlrpc_empty until set. - * Deprecated for public use. See XMLRPC_GetValueTypeEasy - * SEE ALSO - * XMLRPC_SetValue* - * XMLRPC_CreateValue* - * XMLRPC_Append* - * XMLRPC_GetValueTypeEasy () - * SOURCE - */ -XMLRPC_VALUE_TYPE XMLRPC_GetValueType(XMLRPC_VALUE value) { - return value ? value->type : xmlrpc_empty; -} - -/*******/ - -/* Vector type accessor */ -/****f* VALUE/XMLRPC_GetVectorType - * NAME - * XMLRPC_GetVectorType - * SYNOPSIS - * XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) - * FUNCTION - * determine vector type of the XMLRPC_VALUE - * INPUTS - * XMLRPC_VALUE of type xmlrpc_vector - * RESULT - * vector type of value as enumerated by XMLRPC_VECTOR_TYPE. - * xmlrpc_none if not a value. - * NOTES - * xmlrpc_none is returned if value is not a vector - * Deprecated for public use. See XMLRPC_GetValueTypeEasy - * SEE ALSO - * XMLRPC_SetIsVector () - * XMLRPC_GetValueType () - * XMLRPC_GetValueTypeEasy () - * SOURCE - */ -XMLRPC_VECTOR_TYPE XMLRPC_GetVectorType(XMLRPC_VALUE value) { - return(value && value->v) ? value->v->type : xmlrpc_none; -} - -/*******/ - -/****f* VALUE/XMLRPC_GetValueTypeEasy - * NAME - * XMLRPC_GetValueTypeEasy - * SYNOPSIS - * XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy(XMLRPC_VALUE value) - * FUNCTION - * determine data type of the XMLRPC_VALUE. includes vector types. - * INPUTS - * XMLRPC_VALUE target of query - * RESULT - * data type of value as enumerated by XMLRPC_VALUE_TYPE_EASY - * xmlrpc_type_none if not a value. - * NOTES - * all values are of type xmlrpc_type_empty until set. - * SEE ALSO - * XMLRPC_SetValue* - * XMLRPC_CreateValue* - * XMLRPC_Append* - * SOURCE - */ -XMLRPC_VALUE_TYPE_EASY XMLRPC_GetValueTypeEasy (XMLRPC_VALUE value) { - if (value) { - switch (value->type) { - case xmlrpc_vector: - switch (value->v->type) { - case xmlrpc_vector_none: - return xmlrpc_type_none; - case xmlrpc_vector_struct: - return xmlrpc_type_struct; - case xmlrpc_vector_mixed: - return xmlrpc_type_mixed; - case xmlrpc_vector_array: - return xmlrpc_type_array; - } - default: - /* evil cast, but we know they are the same */ - return(XMLRPC_VALUE_TYPE_EASY) value->type; - } - } - return xmlrpc_none; -} - -/*******/ - - - -/*-******************* -* Begin Server Funcs * -*********************/ - - -/****f* VALUE/XMLRPC_ServerCreate - * NAME - * XMLRPC_ServerCreate - * SYNOPSIS - * XMLRPC_SERVER XMLRPC_ServerCreate() - * FUNCTION - * Allocate/Init XMLRPC Server Resources. - * INPUTS - * none - * RESULT - * newly allocated XMLRPC_SERVER - * NOTES - * SEE ALSO - * XMLRPC_ServerDestroy () - * XMLRPC_GetGlobalServer () - * SOURCE - */ -XMLRPC_SERVER XMLRPC_ServerCreate() { - XMLRPC_SERVER server = calloc(1, sizeof(STRUCT_XMLRPC_SERVER)); - if(server) { - Q_Init(&server->methodlist); - Q_Init(&server->docslist); - - /* register system methods */ - xsm_register(server); - } - return server; -} - -/*******/ - -/* Return global server. Not locking! Not Thread Safe! */ -/****f* VALUE/XMLRPC_GetGlobalServer - * NAME - * XMLRPC_GetGlobalServer - * SYNOPSIS - * XMLRPC_SERVER XMLRPC_GetGlobalServer() - * FUNCTION - * Allocates a global (process-wide) server, or returns pointer if pre-existing. - * INPUTS - * none - * RESULT - * pointer to global server, or 0 if error. - * NOTES - * ***WARNING*** This function is not thread safe. It is included only for the very lazy. - * Multi-threaded programs that use this may experience problems. - * BUGS - * There is currently no way to cleanup the global server gracefully. - * SEE ALSO - * XMLRPC_ServerCreate () - * SOURCE - */ -XMLRPC_SERVER XMLRPC_GetGlobalServer() { - static XMLRPC_SERVER xsServer = 0; - if(!xsServer) { - xsServer = XMLRPC_ServerCreate(); - } - return xsServer; -} - -/*******/ - -/****f* VALUE/XMLRPC_ServerDestroy - * NAME - * XMLRPC_ServerDestroy - * SYNOPSIS - * void XMLRPC_ServerDestroy(XMLRPC_SERVER server) - * FUNCTION - * Free Server Resources - * INPUTS - * server The server to be free'd - * RESULT - * void - * NOTES - * This frees the server struct and any methods that have been added. - * SEE ALSO - * XMLRPC_ServerCreate () - * SOURCE - */ -void XMLRPC_ServerDestroy(XMLRPC_SERVER server) { - if(server) { - doc_method* dm = Q_Head(&server->docslist); - server_method* sm = Q_Head(&server->methodlist); - while( dm ) { - my_free(dm); - dm = Q_Next(&server->docslist); - } - while( sm ) { - if(sm->name) { - my_free(sm->name); - } - if(sm->desc) { - XMLRPC_CleanupValue(sm->desc); - } - my_free(sm); - sm = Q_Next(&server->methodlist); - } - if(server->xIntrospection) { - XMLRPC_CleanupValue(server->xIntrospection); - } - - Q_Destroy(&server->methodlist); - Q_Destroy(&server->docslist); - my_free(server); - } -} - -/*******/ - - -/****f* VALUE/XMLRPC_ServerRegisterMethod - * NAME - * XMLRPC_ServerRegisterMethod - * SYNOPSIS - * void XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) - * FUNCTION - * Register new XMLRPC method with server - * INPUTS - * server The XMLRPC_SERVER to register the method with - * name public name of the method - * cb C function that implements the method - * RESULT - * int - 1 if success, else 0 - * NOTES - * A C function must be registered for every "method" that the server recognizes. The - * method name is equivalent to method name in the - * XML syntax. - * SEE ALSO - * XMLRPC_ServerFindMethod () - * XMLRPC_ServerCallMethod () - * SOURCE - */ -int XMLRPC_ServerRegisterMethod(XMLRPC_SERVER server, const char *name, XMLRPC_Callback cb) { - if(server && name && cb) { - - server_method* sm = malloc(sizeof(server_method)); - - if(sm) { - sm->name = strdup(name); - sm->method = cb; - sm->desc = NULL; - - return Q_PushTail(&server->methodlist, sm); - } - } - return 0; -} - -/*******/ - -server_method* find_method(XMLRPC_SERVER server, const char* name) { - server_method* sm; - - q_iter qi = Q_Iter_Head_F(&server->methodlist); - - while( qi ) { - sm = Q_Iter_Get_F(qi); - if(sm && !strcmp(sm->name, name)) { - return sm; - } - qi = Q_Iter_Next_F(qi); - } - return NULL; -} - - -const char* type_to_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype) { - switch(type) { - case xmlrpc_none: - return "none"; - case xmlrpc_empty: - return "empty"; - case xmlrpc_nil: - return "nil"; - case xmlrpc_base64: - return "base64"; - case xmlrpc_boolean: - return "boolean"; - case xmlrpc_datetime: - return "datetime"; - case xmlrpc_double: - return "double"; - case xmlrpc_int: - return "int"; - case xmlrpc_string: - return "string"; - case xmlrpc_vector: - switch(vtype) { - case xmlrpc_vector_none: - return "none"; - case xmlrpc_vector_array: - return "array"; - case xmlrpc_vector_mixed: - return "mixed vector (struct)"; - case xmlrpc_vector_struct: - return "struct"; - } - } - return "unknown"; -} - -/****f* VALUE/XMLRPC_ServerFindMethod - * NAME - * XMLRPC_ServerFindMethod - * SYNOPSIS - * XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) - * FUNCTION - * retrieve C callback associated with a given method name. - * INPUTS - * server The XMLRPC_SERVER the method is registered with - * callName the method to find - * RESULT - * previously registered XMLRPC_Callback, or NULL - * NOTES - * Typically, this is used to determine if a requested method exists, without actually calling it. - * SEE ALSO - * XMLRPC_ServerCallMethod () - * XMLRPC_ServerRegisterMethod () - * SOURCE - */ -XMLRPC_Callback XMLRPC_ServerFindMethod(XMLRPC_SERVER server, const char* callName) { - if(server && callName) { - q_iter qi = Q_Iter_Head_F(&server->methodlist); - while( qi ) { - server_method* sm = Q_Iter_Get_F(qi); - if(sm && !strcmp(sm->name, callName)) { - return sm->method; - } - qi = Q_Iter_Next_F(qi); - } - } - return NULL; -} - -/*******/ - - -/* Call method specified in request */ -/****f* VALUE/XMLRPC_ServerCallMethod - * NAME - * XMLRPC_ServerCallMethod - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) - * FUNCTION - * - * INPUTS - * server The XMLRPC_SERVER the method is registered with - * request the request to handle - * userData any additional data to pass to the C callback, or NULL - * RESULT - * XMLRPC_VALUE allocated by the callback, or NULL - * NOTES - * It is typically the caller's responsibility to free the returned value. - * - * Often the caller will want to serialize the result as XML, via - * XMLRPC_VALUE_To_XML () or XMLRPC_REQUEST_To_XML () - * SEE ALSO - * XMLRPC_ServerFindMethod () - * XMLRPC_ServerRegisterMethod () - * XMLRPC_CleanupValue () - * SOURCE - */ -XMLRPC_VALUE XMLRPC_ServerCallMethod(XMLRPC_SERVER server, XMLRPC_REQUEST request, void* userData) { - XMLRPC_VALUE xReturn = NULL; - - /* check for error set during request parsing / generation */ - if(request && request->error) { - xReturn = XMLRPC_CopyValue(request->error); - } - else if (server && request) { - XMLRPC_Callback cb = - XMLRPC_ServerFindMethod (server, request->methodName.str); - if(cb) { - xReturn = cb(server, request, userData); - } - else { - xReturn = - XMLRPC_UtilityCreateFault (xmlrpc_error_unknown_method, - request->methodName.str); - } - } - return xReturn; -} - -/*******/ - -/*-***************** -* End server funcs * -*******************/ - - -/*-*********************************** -* Begin XMLRPC General Options funcs * -*************************************/ - -/* For options used by XMLRPC_VALUE funcs that otherwise do not have - * parameters for options. Kind of gross. :( - */ -typedef struct _xmlrpc_options { - XMLRPC_CASE id_case; - XMLRPC_CASE_COMPARISON id_case_compare; -} -STRUCT_XMLRPC_OPTIONS, *XMLRPC_OPTIONS; - -static XMLRPC_OPTIONS XMLRPC_GetDefaultOptions() { - static STRUCT_XMLRPC_OPTIONS options = { - xmlrpc_case_exact, - xmlrpc_case_sensitive - }; - return &options; -} - -/****f* VALUE/XMLRPC_GetDefaultIdCase - * NAME - * XMLRPC_GetDefaultIdCase - * SYNOPSIS - * XMLRPC_CASE XMLRPC_GetDefaultIdCase() - * FUNCTION - * Gets default case options used by XMLRPC_VALUE funcs - * INPUTS - * none - * RESULT - * XMLRPC_CASE - * BUGS - * Nasty and gross. Should be server specific, but that requires changing all - * the XMLRPC_VALUE api's. - * SEE ALSO - * XMLRPC_SetDefaultIdCase () - * SOURCE - */ -XMLRPC_CASE XMLRPC_GetDefaultIdCase() { - XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions(); - return options->id_case; -} - -/*******/ - -/****f* VALUE/XMLRPC_SetDefaultIdCase - * NAME - * XMLRPC_SetDefaultIdCase - * SYNOPSIS - * XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) - * FUNCTION - * Sets default case options used by XMLRPC_VALUE funcs - * INPUTS - * id_case case options as enumerated by XMLRPC_CASE - * RESULT - * XMLRPC_CASE -- newly set option - * BUGS - * Nasty and gross. Should be server specific, but that requires changing all - * the XMLRPC_VALUE api's. - * SEE ALSO - * XMLRPC_GetDefaultIdCase () - * SOURCE - */ -XMLRPC_CASE XMLRPC_SetDefaultIdCase(XMLRPC_CASE id_case) { - XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions(); - options->id_case = id_case; - return options->id_case; -} - -/*******/ - -/****f* VALUE/XMLRPC_GetDefaultIdCaseComparison - * NAME - * XMLRPC_GetDefaultIdCaseComparison - * SYNOPSIS - * XMLRPC_CASE XMLRPC_GetDefaultIdCaseComparison( ) - * FUNCTION - * Gets default case comparison options used by XMLRPC_VALUE funcs - * INPUTS - * none - * RESULT - * XMLRPC_CASE_COMPARISON default - * BUGS - * Nasty and gross. Should be server specific, but that requires changing all - * the XMLRPC_VALUE api's. - * SEE ALSO - * XMLRPC_SetDefaultIdCaseComparison () - * SOURCE - */ -XMLRPC_CASE_COMPARISON XMLRPC_GetDefaultIdCaseComparison() { - XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions(); - return options->id_case_compare; -} - -/*******/ - -/****f* VALUE/XMLRPC_SetDefaultIdCaseComparison - * NAME - * XMLRPC_SetDefaultIdCaseComparison - * SYNOPSIS - * XMLRPC_CASE XMLRPC_SetDefaultIdCaseComparison( XMLRPC_CASE_COMPARISON id_case_compare ) - * FUNCTION - * Gets default case comparison options used by XMLRPC_VALUE funcs - * INPUTS - * id_case_compare case comparison rule to set as default - * RESULT - * XMLRPC_CASE_COMPARISON newly set default - * BUGS - * Nasty and gross. Should be server specific, but that requires changing all - * the XMLRPC_VALUE api's. - * SEE ALSO - * XMLRPC_GetDefaultIdCaseComparison () - * SOURCE - */ -XMLRPC_CASE_COMPARISON XMLRPC_SetDefaultIdCaseComparison(XMLRPC_CASE_COMPARISON id_case_compare) { - XMLRPC_OPTIONS options = XMLRPC_GetDefaultOptions(); - options->id_case_compare = id_case_compare; - return options->id_case_compare; -} - -/*******/ - -/*-********************************* -* End XMLRPC General Options funcs * -***********************************/ - - -/*-****************** -* Fault API funcs * -********************/ - -/****f* UTILITY/XMLRPC_UtilityCreateFault - * NAME - * XMLRPC_UtilityCreateFault - * SYNOPSIS - * XMLRPC_VALUE XMLRPC_UtilityCreateFault( int fault_code, const char* fault_string ) - * FUNCTION - * generates a struct containing a string member with id "faultString" and an int member - * with id "faultCode". When using the xmlrpc xml serialization, these will be translated - * to ... format. - * INPUTS - * fault_code application specific error code. can be 0. - * fault_string application specific error string. cannot be null. - * RESULT - * XMLRPC_VALUE a newly created struct vector representing the error, or null on error. - * NOTES - * This is a utility function. xmlrpc "faults" are not directly represented in this xmlrpc - * API or data structures. It is the author's view, that this API is intended for simple - * data types, and a "fault" is a complex data type consisting of multiple simple data - * types. This function is provided for convenience only, the same result could be - * achieved directly by the application. - * - * This function now supports some "standardized" fault codes, as specified at. - * http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php. - * If one of these fault codes is received, the description string will automatically - * be prefixed with a standard error string and 2 newlines. - * - * The actual transformation between this complex type and the xml "" element takes - * place in the xmlrpc to xml serialization layer. This step is not performed when using the - * simplerpc serialization, meaning that there will be no "" element in that - * serialization. There will simply be a standard struct with 2 child elements. - * imho, the "" element is unnecessary and/or out of place as part of the standard API. - * - * SOURCE - */ -XMLRPC_VALUE XMLRPC_UtilityCreateFault(int fault_code, const char* fault_string) { - XMLRPC_VALUE xOutput = NULL; - - char* string = NULL; - simplestring description; - simplestring_init(&description); - - switch (fault_code) { - case xmlrpc_error_parse_xml_syntax: - string = xmlrpc_error_parse_xml_syntax_str; - break; - case xmlrpc_error_parse_unknown_encoding: - string = xmlrpc_error_parse_unknown_encoding_str; - break; - case xmlrpc_error_parse_bad_encoding: - string = xmlrpc_error_parse_bad_encoding_str; - break; - case xmlrpc_error_invalid_xmlrpc: - string = xmlrpc_error_invalid_xmlrpc_str; - break; - case xmlrpc_error_unknown_method: - string = xmlrpc_error_unknown_method_str; - break; - case xmlrpc_error_invalid_params: - string = xmlrpc_error_invalid_params_str; - break; - case xmlrpc_error_internal_server: - string = xmlrpc_error_internal_server_str; - break; - case xmlrpc_error_application: - string = xmlrpc_error_application_str; - break; - case xmlrpc_error_system: - string = xmlrpc_error_system_str; - break; - case xmlrpc_error_transport: - string = xmlrpc_error_transport_str; - break; - } - - simplestring_add(&description, string); - - if(string && fault_string) { - simplestring_add(&description, "\n\n"); - } - simplestring_add(&description, fault_string); - - - if(description.len) { - xOutput = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct); - - XMLRPC_VectorAppendString (xOutput, "faultString", description.str, - description.len); - XMLRPC_VectorAppendInt(xOutput, "faultCode", fault_code); - } - - simplestring_free(&description); - - return xOutput; -} - -/*******/ - - -/****f* FAULT/XMLRPC_ValueIsFault - * NAME - * XMLRPC_ValueIsFault - * SYNOPSIS - * int XMLRPC_ValueIsFault (XMLRPC_VALUE value) - * FUNCTION - * Determines if a value encapsulates a fault "object" - * INPUTS - * value any XMLRPC_VALUE - * RESULT - * 1 if it is a fault, else 0 - * SEE ALSO - * XMLRPC_ResponseIsFault () - * SOURCE - */ -int XMLRPC_ValueIsFault (XMLRPC_VALUE value) { - if( XMLRPC_VectorGetValueWithID(value, "faultCode") && - XMLRPC_VectorGetValueWithID(value, "faultString") ) { - return 1; - } - return 0; -} -/*******/ - - -/****f* FAULT/XMLRPC_ResponseIsFault - * NAME - * XMLRPC_ResponseIsFault - * SYNOPSIS - * int XMLRPC_ResponseIsFault (XMLRPC_REQUEST response) - * FUNCTION - * Determines if a response contains an encapsulated fault "object" - * INPUTS - * value any XMLRPC_REQUEST. typically of type xmlrpc_request_response - * RESULT - * 1 if it contains a fault, else 0 - * SEE ALSO - * XMLRPC_ValueIsFault () - * SOURCE - */ -int XMLRPC_ResponseIsFault(XMLRPC_REQUEST response) { - return XMLRPC_ValueIsFault( XMLRPC_RequestGetData(response) ); -} - -/*******/ - -/****f* FAULT/XMLRPC_GetValueFaultCode - * NAME - * XMLRPC_GetValueFaultCode - * SYNOPSIS - * int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) - * FUNCTION - * returns fault code from a struct, if any - * INPUTS - * value XMLRPC_VALUE of type xmlrpc_vector_struct. - * RESULT - * fault code, else 0. - * BUGS - * impossible to distinguish faultCode == 0 from faultCode not present. - * SEE ALSO - * XMLRPC_GetResponseFaultCode () - * SOURCE - */ -int XMLRPC_GetValueFaultCode (XMLRPC_VALUE value) { - return XMLRPC_VectorGetIntWithID(value, "faultCode"); -} - -/*******/ - -/****f* FAULT/XMLRPC_GetResponseFaultCode - * NAME - * XMLRPC_GetResponseFaultCode - * SYNOPSIS - * int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) - * FUNCTION - * returns fault code from a response, if any - * INPUTS - * response XMLRPC_REQUEST. typically of type xmlrpc_request_response. - * RESULT - * fault code, else 0. - * BUGS - * impossible to distinguish faultCode == 0 from faultCode not present. - * SEE ALSO - * XMLRPC_GetValueFaultCode () - * SOURCE - */ -int XMLRPC_GetResponseFaultCode(XMLRPC_REQUEST response) { - return XMLRPC_GetValueFaultCode( XMLRPC_RequestGetData(response) ); -} - -/*******/ - - -/****f* FAULT/XMLRPC_GetValueFaultString - * NAME - * XMLRPC_GetValueFaultString - * SYNOPSIS - * const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) - * FUNCTION - * returns fault string from a struct, if any - * INPUTS - * value XMLRPC_VALUE of type xmlrpc_vector_struct. - * RESULT - * fault string, else 0. - * SEE ALSO - * XMLRPC_GetResponseFaultString () - * SOURCE - */ -const char* XMLRPC_GetValueFaultString (XMLRPC_VALUE value) { - return XMLRPC_VectorGetStringWithID(value, "faultString"); -} - -/*******/ - -/****f* FAULT/XMLRPC_GetResponseFaultString - * NAME - * XMLRPC_GetResponseFaultString - * SYNOPSIS - * const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) - * FUNCTION - * returns fault string from a response, if any - * INPUTS - * response XMLRPC_REQUEST. typically of type xmlrpc_request_response. - * RESULT - * fault string, else 0. - * SEE ALSO - * XMLRPC_GetValueFaultString () - * SOURCE - */ -const char* XMLRPC_GetResponseFaultString (XMLRPC_REQUEST response) { - return XMLRPC_GetValueFaultString( XMLRPC_RequestGetData(response) ); -} - -/*******/ - - -/*-****************** -* Utility API funcs * -********************/ - - -/****f* UTILITY/XMLRPC_Free - * NAME - * XMLRPC_Free - * SYNOPSIS - * void XMLRPC_Free(void* mem) - * FUNCTION - * frees a block of memory allocated by xmlrpc. - * INPUTS - * mem memory to free - * RESULT - * void - * NOTES - * Useful for OS's where memory must be free'd - * in the same library in which it is allocated. - * SOURCE - */ -void XMLRPC_Free(void* mem) { - my_free(mem); -} - -/*******/ - - -/****f* UTILITY/XMLRPC_GetVersionString - * NAME - * XMLRPC_GetVersionString - * SYNOPSIS - * const char* XMLRPC_GetVersionString() - * FUNCTION - * returns library version string - * INPUTS - * - * RESULT - * const char* - * NOTES - * SOURCE - */ -const char* XMLRPC_GetVersionString() { - return XMLRPC_VERSION_STR; -} - -/*******/ - - -/*-********************** -* End Utility API funcs * -************************/