our own xmlrpc build is about supporting <nil/> - aka allow_none=True
[plcapi.git] / php / xmlrpc / libxmlrpc / xmlrpc.c
diff --git a/php/xmlrpc/libxmlrpc/xmlrpc.c b/php/xmlrpc/libxmlrpc/xmlrpc.c
deleted file mode 100644 (file)
index d5f3f7b..0000000
+++ /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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-#include <ctype.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 %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 <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_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 <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 *
-************************/