our own xmlrpc build is about supporting <nil/> - aka allow_none=True
[plcapi.git] / php / xmlrpc / libxmlrpc / xml_to_soap.c
diff --git a/php/xmlrpc/libxmlrpc/xml_to_soap.c b/php/xmlrpc/libxmlrpc/xml_to_soap.c
deleted file mode 100644 (file)
index 8390f06..0000000
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
-  This file is part of libXMLRPC - a C library for xml-encoded function calls.
-
-  Author: Dan Libby (dan@libby.com)
-*/
-
-
-/*-**********************************************************************
-* TODO:                                                                 *
-*  - [SOAP-ENC:position] read sparse arrays (and write?)                *
-*  - [SOAP-ENC:offset] read partially transmitted arrays  (and write?)  *
-*  - read "flattened" multi-dimensional arrays. (don't bother writing)  *
-*                                                                       *
-* BUGS:                                                                 *
-*  - does not read schema. thus only knows soap pre-defined types.      *
-*  - references (probably) do not work. untested.                       *
-*  - does not expose SOAP-ENV:Header to application at all.             *
-*  - does not use namespaces correctly, thus:                           *
-*    - namespaces are hard-coded in comparison tokens                   *
-*    - if a sender uses another namespace identifer, it will break      *
-************************************************************************/
-
-
-static const char rcsid[] = "#(@) $Id:";
-
-#ifdef _WIN32
-#include "xmlrpc_win32.h"
-#endif
-#include <string.h>
-#include <stdlib.h>
-#include "xml_to_soap.h"
-#include "base64.h"
-
-/* list of tokens used in vocab */
-#define TOKEN_ANY                               "xsd:ur-type"
-#define TOKEN_ARRAY          "SOAP-ENC:Array"
-#define TOKEN_ARRAY_TYPE     "SOAP-ENC:arrayType"
-#define TOKEN_BASE64         "SOAP-ENC:base64"
-#define TOKEN_BOOLEAN        "xsd:boolean"
-#define TOKEN_DATETIME       "xsd:timeInstant"
-#define TOKEN_DOUBLE         "xsd:double"
-#define TOKEN_FLOAT          "xsd:float"
-#define TOKEN_ID             "id"
-#define TOKEN_INT            "xsd:int"
-#define TOKEN_NULL           "xsi:null"
-#define TOKEN_STRING         "xsd:string"
-#define TOKEN_STRUCT                    "xsd:struct"
-#define TOKEN_TYPE           "xsi:type"
-#define TOKEN_FAULT                     "SOAP-ENV:Fault"
-#define TOKEN_MUSTUNDERSTAND "SOAP-ENV:mustUnderstand"
-#define TOKEN_ACTOR                     "SOAP-ENV:actor"
-#define TOKEN_ACTOR_NEXT                "http://schemas.xmlsoap.org/soap/actor/next"
-
-#define TOKEN_XMLRPC_FAULTCODE   "faultCode"
-#define TOKEN_XMLRPC_FAULTSTRING "faultString"
-#define TOKEN_SOAP_FAULTCODE     "faultcode"
-#define TOKEN_SOAP_FAULTSTRING   "faultstring"
-#define TOKEN_SOAP_FAULTDETAILS  "details"
-#define TOKEN_SOAP_FAULTACTOR    "actor"
-
-
-/* determine if a string represents a soap type, as used in element names */
-static inline int is_soap_type(const char* soap_type) {
-       return(strstr(soap_type, "SOAP-ENC:") || strstr(soap_type, "xsd:")) ? 1 : 0;
-}
-
-/* utility func to generate a new attribute. possibly should be in xml_element.c?? */
-static xml_element_attr* new_attr(const char* key, const char* val) {
-       xml_element_attr* attr = malloc(sizeof(xml_element_attr));
-       if (attr) {
-               attr->key = key ? strdup(key) : NULL;
-               attr->val = val ? strdup(val) : NULL;
-       }
-       return attr;
-}
-
-struct array_info {
-       char          kids_type[30];
-       unsigned long size;
-       /* ... ? */
-};
-
-
-/* parses soap arrayType attribute to generate an array_info structure.
- * TODO: should deal with sparse, flattened, & multi-dimensional arrays
- */
-static struct array_info* parse_array_type_info(const char* array_type) {
-       struct array_info* ai = NULL;
-       if (array_type) {
-               ai = (struct array_info*)calloc(1, sizeof(struct array_info));
-               if (ai) {
-                       char buf[128], *p;
-                       snprintf(buf, sizeof(buf), "%s", array_type);
-                       p = strchr(buf, '[');
-                       if (p) {
-                               *p = 0;
-                       }
-                       strcpy(ai->kids_type, buf);
-               }
-       }
-       return ai;
-}
-
-/* performs heuristics on an xmlrpc_vector_array to determine
- * appropriate soap arrayType string.
- */
-static const char* get_array_soap_type(XMLRPC_VALUE node) {
-       XMLRPC_VALUE_TYPE_EASY type = xmlrpc_type_none;
-
-       XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
-       int loopCount = 0;
-       const char* soapType = TOKEN_ANY;
-
-       type = XMLRPC_GetValueTypeEasy(xIter);
-       xIter = XMLRPC_VectorNext(node);
-
-       while (xIter) {
-               /* 50 seems like a decent # of loops.  That will likely
-                * cover most cases.  Any more and we start to sacrifice
-                * performance.
-                */
-               if ( (XMLRPC_GetValueTypeEasy(xIter) != type) || loopCount >= 50) {
-                       type = xmlrpc_type_none;
-                       break;
-               }
-               loopCount ++;
-
-               xIter = XMLRPC_VectorNext(node);
-       }
-       switch (type) {
-       case xmlrpc_type_none:
-               soapType = TOKEN_ANY;
-               break;
-       case xmlrpc_type_empty:
-               soapType = TOKEN_NULL;
-               break;
-       case xmlrpc_type_int:
-               soapType = TOKEN_INT;
-               break;
-       case xmlrpc_type_double:
-               soapType = TOKEN_DOUBLE;
-               break;
-       case xmlrpc_type_boolean:
-               soapType = TOKEN_BOOLEAN;
-               break;
-       case xmlrpc_type_string:
-               soapType = TOKEN_STRING;
-               break;
-       case xmlrpc_type_base64:
-               soapType = TOKEN_BASE64;
-               break;
-       case xmlrpc_type_datetime:
-               soapType = TOKEN_DATETIME;
-               break;
-       case xmlrpc_type_struct:
-               soapType = TOKEN_STRUCT;
-               break;
-       case xmlrpc_type_array:
-               soapType = TOKEN_ARRAY;
-               break;
-       case xmlrpc_type_mixed:
-               soapType = TOKEN_STRUCT;
-               break;
-       }
-       return soapType;
-}
-
-/* determines wether a node is a fault or not, and of which type:
- * 0 = not a fault,
- * 1 = xmlrpc style fault
- * 2 = soap style fault.
- */
-static inline int get_fault_type(XMLRPC_VALUE node) {
-       if (XMLRPC_VectorGetValueWithID(node, TOKEN_XMLRPC_FAULTCODE) &&
-                XMLRPC_VectorGetValueWithID(node, TOKEN_XMLRPC_FAULTSTRING)) {
-               return 1;
-       }
-       else if (XMLRPC_VectorGetValueWithID(node, TOKEN_SOAP_FAULTCODE) &&
-                               XMLRPC_VectorGetValueWithID(node, TOKEN_SOAP_FAULTSTRING)) {
-               return 2;
-       }
-       return 0;
-}
-
-/* input: an XMLRPC_VALUE representing a fault struct in xml-rpc style.
- * output: an XMLRPC_VALUE representing a fault struct in soap style,
- *  with xmlrpc codes mapped to soap codes, and all other values preserved.
- *  note that the returned value is a completely new value, and must be freed.
- *  the input value is untouched.
- */
-static XMLRPC_VALUE gen_fault_xmlrpc(XMLRPC_VALUE node, xml_element* el_target) {
-       XMLRPC_VALUE xDup = XMLRPC_DupValueNew(node);
-       XMLRPC_VALUE xCode = XMLRPC_VectorGetValueWithID(xDup, TOKEN_XMLRPC_FAULTCODE);
-       XMLRPC_VALUE xStr = XMLRPC_VectorGetValueWithID(xDup, TOKEN_XMLRPC_FAULTSTRING);
-
-       XMLRPC_SetValueID(xCode, TOKEN_SOAP_FAULTCODE, 0);
-       XMLRPC_SetValueID(xStr, TOKEN_SOAP_FAULTSTRING, 0);
-
-       /* rough mapping of xmlrpc fault codes to soap codes */
-       switch (XMLRPC_GetValueInt(xCode)) {
-       case -32700:              /* "parse error. not well formed", */
-       case -32701:              /* "parse error. unsupported encoding" */
-       case -32702:              /* "parse error. invalid character for encoding" */
-       case -32600:              /* "server error. invalid xml-rpc.  not conforming to spec." */
-       case -32601:              /* "server error. requested method not found" */
-       case -32602:              /* "server error. invalid method parameters" */
-               XMLRPC_SetValueString(xCode, "SOAP-ENV:Client", 0);
-               break;
-       case -32603:              /* "server error. internal xml-rpc error" */
-       case -32500:              /* "application error" */
-       case -32400:              /* "system error" */
-       case -32300:              /* "transport error */
-               XMLRPC_SetValueString(xCode, "SOAP-ENV:Server", 0);
-               break;
-       }
-       return xDup;
-}
-
-/* returns a new XMLRPC_VALUE representing a soap fault, comprised of a struct with four keys. */
-static XMLRPC_VALUE gen_soap_fault(const char* fault_code, const char* fault_string, 
-                                                                                         const char* actor, const char* details) {
-       XMLRPC_VALUE xReturn = XMLRPC_CreateVector(TOKEN_FAULT, xmlrpc_vector_struct);
-       XMLRPC_AddValuesToVector(xReturn,
-                                                                        XMLRPC_CreateValueString(TOKEN_SOAP_FAULTCODE, fault_code, 0),
-                                                                        XMLRPC_CreateValueString(TOKEN_SOAP_FAULTSTRING, fault_string, 0),
-                                                                        XMLRPC_CreateValueString(TOKEN_SOAP_FAULTACTOR, actor, 0),
-                                                                        XMLRPC_CreateValueString(TOKEN_SOAP_FAULTDETAILS, details, 0),
-                                                                        NULL);
-       return xReturn;
-}
-
-/* translates xml soap dom to native data structures. recursive. */
-XMLRPC_VALUE xml_element_to_SOAP_REQUEST_worker(XMLRPC_REQUEST request, 
-                                                                                                                               XMLRPC_VALUE xParent,
-                                                                                                                               struct array_info* parent_array,
-                                                                                                                               XMLRPC_VALUE xCurrent, 
-                                                                                                                               xml_element* el, 
-                                                                                                                               int depth) {
-       XMLRPC_REQUEST_TYPE rtype = xmlrpc_request_none;
-
-       /* no current element on first call */
-       if (!xCurrent) {
-               xCurrent = XMLRPC_CreateValueEmpty();
-       }
-
-       /* increment recursion depth guage */
-       depth ++;
-
-       /* safety first. must have a valid element */
-       if (el && el->name) {
-               const char* id = NULL;
-               const char* type = NULL, *arrayType=NULL, *actor = NULL;
-               xml_element_attr* attr_iter = Q_Head(&el->attrs);
-               int b_must_understand = 0;
-               
-               /* in soap, types may be specified in either element name -or- with xsi:type attribute. */
-               if (is_soap_type(el->name)) {
-                       type = el->name;
-               }
-               /* if our parent node, by definition a vector, is not an array, then
-                  our element name must be our key identifier. */
-               else if (XMLRPC_GetVectorType(xParent) != xmlrpc_vector_array) {
-                       id = el->name;
-                       if(!strcmp(id, "item")) {
-                       }
-               }
-
-               /* iterate through element attributes, pick out useful stuff. */
-               while (attr_iter) {
-                       /* element's type */
-                       if (!strcmp(attr_iter->key, TOKEN_TYPE)) {
-                               type = attr_iter->val;
-                       }
-                       /* array type */
-                       else if (!strcmp(attr_iter->key, TOKEN_ARRAY_TYPE)) {
-                               arrayType = attr_iter->val;
-                       }
-                       /* must understand, sometimes present in headers. */
-                       else if (!strcmp(attr_iter->key, TOKEN_MUSTUNDERSTAND)) {
-                               b_must_understand = strchr(attr_iter->val, '1') ? 1 : 0;
-                       }
-                       /* actor, used in conjuction with must understand. */
-                       else if (!strcmp(attr_iter->key, TOKEN_ACTOR)) {
-                               actor = attr_iter->val;
-                       }
-                       attr_iter = Q_Next(&el->attrs);
-               }
-
-               /* check if caller says we must understand something in a header. */
-               if (b_must_understand) {
-                       /* is must understand actually indended for us?
-                          BUG: spec says we should also determine if actor is our URL, but
-                               we do not have that information. */
-                       if (!actor || !strcmp(actor, TOKEN_ACTOR_NEXT)) {
-                               /* TODO: implement callbacks or other mechanism for applications
-                                  to "understand" these headers. For now, we just bail if we
-                                  get a mustUnderstand header intended for us. */
-                               XMLRPC_RequestSetError(request, 
-                                                                                         gen_soap_fault("SOAP-ENV:MustUnderstand",
-                                                                                                                                 "SOAP Must Understand Error",
-                                                                                                                                 "", ""));
-                               return xCurrent;
-                       }
-               }
-
-               /* set id (key) if one was found. */
-               if (id) {
-                       XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
-               }
-
-               /* according to soap spec, 
-                  depth 1 = Envelope, 2 = Header, Body & Fault, 3 = methodcall or response. */
-               if (depth == 3) {
-                       const char* methodname = el->name;
-                       char* p = NULL;
-
-                       /* BUG: we determine request or response type using presence of "Response" in element name.
-                          According to spec, this is only recommended, not required. Apparently, implementations
-                          are supposed to know the type of action based on state, which strikes me as a bit lame.
-                          Anyway, we don't have that state info, thus we use Response as a heuristic. */
-                       rtype =
-#ifdef strcasestr
-                       strcasestr(el->name, "response") ? xmlrpc_request_response : xmlrpc_request_call;
-#else
-                       strstr(el->name, "esponse") ? xmlrpc_request_response : xmlrpc_request_call;
-#endif
-                       XMLRPC_RequestSetRequestType(request, rtype);
-
-                       /* Get methodname.  strip xml namespace crap. */
-                       p = strchr(el->name, ':');
-                       if (p) {
-                               methodname = p + 1;
-                       }
-                       if (rtype == xmlrpc_request_call) {
-                               XMLRPC_RequestSetMethodName(request, methodname);
-                       }
-               }
-
-
-               /* Next, we begin to convert actual values. if no children, then must be a scalar value. */
-               if (!Q_Size(&el->children)) {
-                       if (!type && parent_array && parent_array->kids_type[0]) {
-                               type = parent_array->kids_type;
-                       }
-                       if (!type || !strcmp(type, TOKEN_STRING)) {
-                               XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
-                       }
-                       else if (!strcmp(type, TOKEN_INT)) {
-                               XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
-                       }
-                       else if (!strcmp(type, TOKEN_BOOLEAN)) {
-                               XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
-                       }
-                       else if (!strcmp(type, TOKEN_DOUBLE) ||
-                                               !strcmp(type, TOKEN_FLOAT)) {
-                               XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
-                       }
-                       else if (!strcmp(type, TOKEN_NULL)) {
-                               /* already an empty val. do nothing. */
-                       }
-                       else if (!strcmp(type, TOKEN_DATETIME)) {
-                               XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
-                       }
-                       else if (!strcmp(type, TOKEN_BASE64)) {
-                               struct buffer_st buf;
-                               base64_decode(&buf, el->text.str, el->text.len);
-                               XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
-                               buffer_delete(&buf);
-                       }
-               }
-               /* Element has children, thus a vector, or "compound type" in soap-speak. */
-               else {
-                       struct array_info* ai = NULL;
-                       xml_element* iter = (xml_element*)Q_Head(&el->children);
-
-                       if (!type || !strcmp(type, TOKEN_STRUCT)) {
-                               XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
-                       }
-                       else if (!strcmp(type, TOKEN_ARRAY) || arrayType != NULL) {
-                               /* determine magic associated with soap array type.
-                                  this is passed down as we recurse, so our children have access to the info. */
-                               ai = parse_array_type_info(arrayType);  // alloc'ed ai free'd below.
-                               XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
-                       }
-                       else {
-                               /* mixed is probably closest thing we have to compound type. */
-                               XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
-                       }
-                       /* Recurse, adding values as we go.  Check for error during recursion
-                          and if found, bail.  this short-circuits us out of the recursion. */
-                       while ( iter && !XMLRPC_RequestGetError(request) ) {
-                               XMLRPC_VALUE xNext = NULL;
-                               /* top level elements don't actually represent values, so we just pass the
-                                  current value along until we are deep enough. */
-                               if ( depth <= 2 ||
-                                         (rtype == xmlrpc_request_response && depth <= 3) ) {
-                                       xml_element_to_SOAP_REQUEST_worker(request, NULL, ai, xCurrent, iter, depth);
-                               }
-                               /* ready to do some actual de-serialization. create a new empty value and
-                                  pass that along to be init'd, then add it to our current vector. */
-                               else {
-                                       xNext = XMLRPC_CreateValueEmpty();
-                                       xml_element_to_SOAP_REQUEST_worker(request, xCurrent, ai, xNext, iter, depth);
-                                       XMLRPC_AddValueToVector(xCurrent, xNext);
-                               }
-                               iter = (xml_element*)Q_Next(&el->children);
-                       }
-                       /* cleanup */
-                       if (ai) {
-                               free(ai);
-                       }
-               }
-       }
-       return xCurrent;
-}
-
-/* Convert soap xml dom to XMLRPC_VALUE, sans request info.  untested. */
-XMLRPC_VALUE xml_element_to_SOAP_VALUE(xml_element* el)
-{
-       return xml_element_to_SOAP_REQUEST_worker(NULL, NULL, NULL, NULL, el, 0);
-}
-
-/* Convert soap xml dom to XMLRPC_REQUEST */
-XMLRPC_VALUE xml_element_to_SOAP_REQUEST(XMLRPC_REQUEST request, xml_element* el)
-{
-       if (request) {
-               return XMLRPC_RequestSetData(request, xml_element_to_SOAP_REQUEST_worker(request, NULL, NULL, NULL, el, 0));
-       }
-       return NULL;
-}
-
-
-/* translates data structures to soap/xml. recursive */
-xml_element* SOAP_to_xml_element_worker(XMLRPC_REQUEST request, XMLRPC_VALUE node) {
-#define BUF_SIZE 128
-       xml_element* elem_val = NULL;
-       if (node) {
-               int bFreeNode = 0;  /* sometimes we may need to free 'node' variable */
-               char buf[BUF_SIZE];
-               XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(node);
-               char* pName = NULL, *pAttrType = NULL;
-
-               /* create our return value element */
-               elem_val = xml_elem_new();
-
-               switch (type) {
-               case xmlrpc_type_struct:
-               case xmlrpc_type_mixed:
-               case xmlrpc_type_array:
-                       if (type == xmlrpc_type_array) {
-                               /* array's are _very_ special in soap.
-                                  TODO: Should handle sparse/partial arrays here. */
-
-                               /* determine soap array type. */
-                               const char* type = get_array_soap_type(node);
-                               xml_element_attr* attr_array_type = NULL;
-
-                               /* specify array kids type and array size. */
-                               snprintf(buf, sizeof(buf), "%s[%i]", type, XMLRPC_VectorSize(node));
-                               attr_array_type = new_attr(TOKEN_ARRAY_TYPE, buf);
-
-                               Q_PushTail(&elem_val->attrs, attr_array_type);
-
-                               pAttrType = TOKEN_ARRAY;
-                       }
-                       /* check for fault, which is a rather special case. 
-                          (can't these people design anything consistent/simple/elegant?) */
-                       else if (type == xmlrpc_type_struct) {
-                               int fault_type = get_fault_type(node);
-                               if (fault_type) {
-                                       if (fault_type == 1) {
-                                               /* gen fault from xmlrpc style fault codes              
-                                                   notice that we get a new node, which must be freed herein. */
-                                               node = gen_fault_xmlrpc(node, elem_val);
-                                               bFreeNode = 1;
-                                       }
-                                       pName = TOKEN_FAULT;
-                               }
-                       }
-
-                       {
-                               /* recurse through sub-elements */
-                               XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
-                               while ( xIter ) {
-                                       xml_element* next_el = SOAP_to_xml_element_worker(request, xIter);
-                                       if (next_el) {
-                                               Q_PushTail(&elem_val->children, next_el);
-                                       }
-                                       xIter = XMLRPC_VectorNext(node);
-                               }
-                       }
-
-                       break;
-
-                       /* handle scalar types */
-               case xmlrpc_type_empty:
-                       pAttrType = TOKEN_NULL;
-                       break;
-               case xmlrpc_type_string:
-                       pAttrType = TOKEN_STRING;
-                       simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node));
-                       break;
-               case xmlrpc_type_int:
-                       pAttrType = TOKEN_INT;
-                       snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node));
-                       simplestring_add(&elem_val->text, buf);
-                       break;
-               case xmlrpc_type_boolean:
-                       pAttrType = TOKEN_BOOLEAN;
-                       snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node));
-                       simplestring_add(&elem_val->text, buf);
-                       break;
-               case xmlrpc_type_double:
-                       pAttrType = TOKEN_DOUBLE;
-                       snprintf(buf, BUF_SIZE, "%f", XMLRPC_GetValueDouble(node));
-                       simplestring_add(&elem_val->text, buf);
-                       break;
-               case xmlrpc_type_datetime:
-                       {
-                               time_t tt = XMLRPC_GetValueDateTime(node);
-                               struct tm *tm = localtime (&tt);
-                               pAttrType = TOKEN_DATETIME;
-                               if(strftime (buf, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", tm)) {
-                                       simplestring_add(&elem_val->text, buf);
-                               }
-                       }
-                       break;
-               case xmlrpc_type_base64:
-                       {
-                               struct buffer_st buf;
-                               pAttrType = TOKEN_BASE64;
-                               base64_encode(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node));
-                               simplestring_addn(&elem_val->text, buf.data, buf.offset );
-                               buffer_delete(&buf);
-                       }
-                       break;
-                       break;
-               default:
-                       break;
-               }
-
-               /* determining element's name is a bit tricky, due to soap semantics. */
-               if (!pName) {
-                       /* if the value's type is known... */
-                       if (pAttrType) {
-                               /* see if it has an id (key). If so, use that as name, and type as an attribute. */
-                               pName = (char*)XMLRPC_GetValueID(node);
-                               if (pName) {
-                                       Q_PushTail(&elem_val->attrs, new_attr(TOKEN_TYPE, pAttrType));
-                               }
-
-                               /* otherwise, use the type as the name. */
-                               else {
-                                       pName = pAttrType;
-                               }
-                       }
-                       /* if the value's type is not known... (a rare case?) */
-                       else {
-                               /* see if it has an id (key). otherwise, default to generic "item" */
-                               pName = (char*)XMLRPC_GetValueID(node);
-                               if (!pName) {
-                                       pName = "item";
-                               }
-                       }
-               }
-               elem_val->name = strdup(pName);
-
-               /* cleanup */
-               if (bFreeNode) {
-                       XMLRPC_CleanupValue(node);
-               }
-       }
-       return elem_val;
-}
-
-/* convert XMLRPC_VALUE to soap xml dom.  untested. */
-xml_element* SOAP_VALUE_to_xml_element(XMLRPC_VALUE node) {
-       return SOAP_to_xml_element_worker(NULL, node);
-}
-
-/* convert XMLRPC_REQUEST to soap xml dom. */
-xml_element* SOAP_REQUEST_to_xml_element(XMLRPC_REQUEST request) {
-       xml_element* root = xml_elem_new();
-
-       /* safety first. */
-       if (root) {
-               xml_element* body = xml_elem_new();
-               root->name = strdup("SOAP-ENV:Envelope");
-
-               /* silly namespace stuff */
-               Q_PushTail(&root->attrs, new_attr("xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"));
-               Q_PushTail(&root->attrs, new_attr("xmlns:xsi", "http://www.w3.org/1999/XMLSchema-instance"));
-               Q_PushTail(&root->attrs, new_attr("xmlns:xsd", "http://www.w3.org/1999/XMLSchema"));
-               Q_PushTail(&root->attrs, new_attr("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"));
-               Q_PushTail(&root->attrs, new_attr("xmlns:si", "http://soapinterop.org/xsd"));
-               Q_PushTail(&root->attrs, new_attr("xmlns:ns6", "http://testuri.org"));
-               Q_PushTail(&root->attrs, new_attr("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"));
-
-               /* Q_PushHead(&root->attrs, new_attr("xmlns:ks", "http://kitchen.sink.org/soap/everything/under/sun"));
-                      JUST KIDDING!! :-)  ---->                ------------------------------------------------- */
-
-               if (body) {
-                       /* go ahead and serialize first... */
-                       xml_element* el_serialized =  
-                       SOAP_to_xml_element_worker(request, 
-                                                                                               XMLRPC_RequestGetData(request));
-
-                       /* check for fault, in which case, there is no intermediate element */
-                       if (el_serialized && !strcmp(el_serialized->name, TOKEN_FAULT)) {
-                               Q_PushTail(&body->children, el_serialized);
-                       }
-                       /* usual case: not a fault. Add Response element in between. */
-                       else {
-                               xml_element* rpc = xml_elem_new();
-
-                               if (rpc) {
-                                       const char* methodname = XMLRPC_RequestGetMethodName(request);
-                                       XMLRPC_REQUEST_TYPE rtype = XMLRPC_RequestGetRequestType(request);
-
-                                       /* if we are making a request, we want to use the methodname as is. */
-                                       if (rtype == xmlrpc_request_call) {
-                                               if (methodname) {
-                                                       rpc->name = strdup(methodname);
-                                               }
-                                       }
-                                       /* if it's a response, we append "Response". Also, given xmlrpc-epi
-                                          API/architecture, it's likely that we don't have a methodname for
-                                          the response, so we have to check that. */
-                                       else {
-                                               char buf[128];
-                                               snprintf(buf, sizeof(buf), "%s%s", 
-                                                                       methodname ? methodname : "",
-                                                                       "Response");
-
-                                               rpc->name = strdup(buf);
-                                       }
-
-                                       /* add serialized data to method call/response.
-                                          add method call/response to body element */
-                                       if (rpc->name) {
-                                               if(el_serialized) {
-                                                       if(Q_Size(&el_serialized->children) && rtype == xmlrpc_request_call) {
-                                                               xml_element* iter = (xml_element*)Q_Head(&el_serialized->children);
-                                                               while(iter) {
-                                                                       Q_PushTail(&rpc->children, iter);
-                                                                       iter = (xml_element*)Q_Next(&el_serialized->children);
-                                                               }
-                                                               xml_elem_free_non_recurse(el_serialized);
-                                                       }
-                                                       else {
-                                                               Q_PushTail(&rpc->children, el_serialized);
-                                                       }
-                                               }
-
-                                               Q_PushTail(&body->children, rpc);
-                                       }
-                                       else {
-                                               /* no method name?!
-                                                  TODO: fault here...? */
-                                       }
-                               }
-                       }
-                       body->name = strdup("SOAP-ENV:Body");
-                       Q_PushTail(&root->children, body);
-               }
-       }
-
-       return root;
-}
-