summaryrefslogtreecommitdiff
path: root/ext/xmlrpc/libxmlrpc/xmlrpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/xmlrpc/libxmlrpc/xmlrpc.c')
-rw-r--r--ext/xmlrpc/libxmlrpc/xmlrpc.c2956
1 files changed, 0 insertions, 2956 deletions
diff --git a/ext/xmlrpc/libxmlrpc/xmlrpc.c b/ext/xmlrpc/libxmlrpc/xmlrpc.c
deleted file mode 100644
index 3eca7065a8..0000000000
--- a/ext/xmlrpc/libxmlrpc/xmlrpc.c
+++ /dev/null
@@ -1,2956 +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$
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-
-#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 %i, column %i, byte index %i",
- 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;
-}
-
-static const char* get_string(const char* buf, int bDup) {
- if(bDup) {
- return strdup(buf);
- }
- return buf;
-}
-
-/*******/
-
-/****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) {
- XMLRPC_VECTOR *pSIV = NULL;
-
- 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_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;
- }
- }
- 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 <methodCall><name> method name </name></methodCall> 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_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";
- }
- }
-}
-
-/****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 <fault><value><struct>... 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 "<fault>" 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 "<fault>" element in that
- * serialization. There will simply be a standard struct with 2 child elements.
- * imho, the "<fault>" 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 *
-************************/