Back to index

php5  5.3.10
Classes | Defines | Functions | Variables
xml_to_soap.c File Reference
#include <string.h>
#include <stdlib.h>
#include "xml_to_soap.h"
#include "base64.h"

Go to the source code of this file.

Classes

struct  array_info

Defines

#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"
#define BUF_SIZE   128

Functions

static int is_soap_type (const char *soap_type)
static xml_element_attrnew_attr (const char *key, const char *val)
static struct array_infoparse_array_type_info (const char *array_type)
static const char * get_array_soap_type (XMLRPC_VALUE node)
static int get_fault_type (XMLRPC_VALUE node)
static XMLRPC_VALUE gen_fault_xmlrpc (XMLRPC_VALUE node, xml_element *el_target)
static XMLRPC_VALUE gen_soap_fault (const char *fault_code, const char *fault_string, const char *actor, const char *details)
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_VALUE xml_element_to_SOAP_VALUE (xml_element *el)
XMLRPC_VALUE xml_element_to_SOAP_REQUEST (XMLRPC_REQUEST request, xml_element *el)
xml_elementSOAP_to_xml_element_worker (XMLRPC_REQUEST request, XMLRPC_VALUE node)
xml_elementSOAP_VALUE_to_xml_element (XMLRPC_VALUE node)
xml_elementSOAP_REQUEST_to_xml_element (XMLRPC_REQUEST request)

Variables

static const char rcsid [] = "#(@) $Id:"

Class Documentation

struct array_info

Definition at line 77 of file xml_to_soap.c.

Class Members
char kids_type
unsigned long size

Define Documentation

#define BUF_SIZE   128
#define TOKEN_ACTOR   "SOAP-ENV:actor"

Definition at line 51 of file xml_to_soap.c.

#define TOKEN_ACTOR_NEXT   "http://schemas.xmlsoap.org/soap/actor/next"

Definition at line 52 of file xml_to_soap.c.

#define TOKEN_ANY   "xsd:ur-type"

Definition at line 35 of file xml_to_soap.c.

#define TOKEN_ARRAY   "SOAP-ENC:Array"

Definition at line 36 of file xml_to_soap.c.

#define TOKEN_ARRAY_TYPE   "SOAP-ENC:arrayType"

Definition at line 37 of file xml_to_soap.c.

#define TOKEN_BASE64   "SOAP-ENC:base64"

Definition at line 38 of file xml_to_soap.c.

#define TOKEN_BOOLEAN   "xsd:boolean"

Definition at line 39 of file xml_to_soap.c.

#define TOKEN_DATETIME   "xsd:timeInstant"

Definition at line 40 of file xml_to_soap.c.

#define TOKEN_DOUBLE   "xsd:double"

Definition at line 41 of file xml_to_soap.c.

#define TOKEN_FAULT   "SOAP-ENV:Fault"

Definition at line 49 of file xml_to_soap.c.

#define TOKEN_FLOAT   "xsd:float"

Definition at line 42 of file xml_to_soap.c.

#define TOKEN_ID   "id"

Definition at line 43 of file xml_to_soap.c.

#define TOKEN_INT   "xsd:int"

Definition at line 44 of file xml_to_soap.c.

#define TOKEN_MUSTUNDERSTAND   "SOAP-ENV:mustUnderstand"

Definition at line 50 of file xml_to_soap.c.

#define TOKEN_NULL   "xsi:null"

Definition at line 45 of file xml_to_soap.c.

#define TOKEN_SOAP_FAULTACTOR   "actor"

Definition at line 59 of file xml_to_soap.c.

#define TOKEN_SOAP_FAULTCODE   "faultcode"

Definition at line 56 of file xml_to_soap.c.

#define TOKEN_SOAP_FAULTDETAILS   "details"

Definition at line 58 of file xml_to_soap.c.

#define TOKEN_SOAP_FAULTSTRING   "faultstring"

Definition at line 57 of file xml_to_soap.c.

#define TOKEN_STRING   "xsd:string"

Definition at line 46 of file xml_to_soap.c.

#define TOKEN_STRUCT   "xsd:struct"

Definition at line 47 of file xml_to_soap.c.

#define TOKEN_TYPE   "xsi:type"

Definition at line 48 of file xml_to_soap.c.

#define TOKEN_XMLRPC_FAULTCODE   "faultCode"

Definition at line 54 of file xml_to_soap.c.

#define TOKEN_XMLRPC_FAULTSTRING   "faultString"

Definition at line 55 of file xml_to_soap.c.


Function Documentation

static XMLRPC_VALUE gen_fault_xmlrpc ( XMLRPC_VALUE  node,
xml_element el_target 
) [static]

Definition at line 191 of file xml_to_soap.c.

                                                                                {
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static XMLRPC_VALUE gen_soap_fault ( const char *  fault_code,
const char *  fault_string,
const char *  actor,
const char *  details 
) [static]

Definition at line 220 of file xml_to_soap.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* get_array_soap_type ( XMLRPC_VALUE  node) [static]

Definition at line 107 of file xml_to_soap.c.

                                                          {
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_fault_type ( XMLRPC_VALUE  node) [inline, static]

Definition at line 173 of file xml_to_soap.c.

Here is the caller graph for this function:

static int is_soap_type ( const char *  soap_type) [inline, static]

Definition at line 63 of file xml_to_soap.c.

                                                      {
       return(strstr(soap_type, "SOAP-ENC:") || strstr(soap_type, "xsd:")) ? 1 : 0;
}

Here is the caller graph for this function:

static xml_element_attr* new_attr ( const char *  key,
const char *  val 
) [static]

Definition at line 68 of file xml_to_soap.c.

                                                                    {
       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;
}

Here is the caller graph for this function:

static struct array_info* parse_array_type_info ( const char *  array_type) [static, read]

Definition at line 87 of file xml_to_soap.c.

                                                                        {
       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;
}

Here is the caller graph for this function:

Definition at line 582 of file xml_to_soap.c.

                                                                 {
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 434 of file xml_to_soap.c.

                                                                                   {
#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_xmlrpc(&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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 577 of file xml_to_soap.c.

                                                          {
       return SOAP_to_xml_element_worker(NULL, node);
}

Here is the call graph for this function:

Definition at line 424 of file xml_to_soap.c.

{
       if (request) {
              return XMLRPC_RequestSetData(request, xml_element_to_SOAP_REQUEST_worker(request, NULL, NULL, NULL, el, 0));
       }
       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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 
)

Definition at line 233 of file xml_to_soap.c.

                                                                                                                           {
       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_xmlrpc(&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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 418 of file xml_to_soap.c.

Here is the call graph for this function:


Variable Documentation

const char rcsid[] = "#(@) $Id:" [static]

Definition at line 24 of file xml_to_soap.c.