123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- 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"
- #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"
- static inline int is_soap_type(const char* soap_type) {
- return(strstr(soap_type, "SOAP-ENC:") || strstr(soap_type, "xsd:")) ? 1 : 0;
- }
- 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[128];
- unsigned long size;
-
- };
- 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;
- }
- 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) {
-
- 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;
- }
- 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;
- }
- 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);
-
- switch (XMLRPC_GetValueInt(xCode)) {
- case -32700:
- case -32701:
- case -32702:
- case -32600:
- case -32601:
- case -32602:
- XMLRPC_SetValueString(xCode, "SOAP-ENV:Client", 0);
- break;
- case -32603:
- case -32500:
- case -32400:
- case -32300:
- XMLRPC_SetValueString(xCode, "SOAP-ENV:Server", 0);
- break;
- }
- return xDup;
- }
- 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;
- }
- 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;
-
- if (!xCurrent) {
- xCurrent = XMLRPC_CreateValueEmpty();
- }
-
- depth ++;
-
- 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;
-
-
- if (is_soap_type(el->name)) {
- type = el->name;
- }
-
- else if (XMLRPC_GetVectorType(xParent) != xmlrpc_vector_array) {
- id = el->name;
- if(!strcmp(id, "item")) {
- }
- }
-
- while (attr_iter) {
-
- if (!strcmp(attr_iter->key, TOKEN_TYPE)) {
- type = attr_iter->val;
- }
-
- else if (!strcmp(attr_iter->key, TOKEN_ARRAY_TYPE)) {
- arrayType = attr_iter->val;
- }
-
- else if (!strcmp(attr_iter->key, TOKEN_MUSTUNDERSTAND)) {
- b_must_understand = strchr(attr_iter->val, '1') ? 1 : 0;
- }
-
- else if (!strcmp(attr_iter->key, TOKEN_ACTOR)) {
- actor = attr_iter->val;
- }
- attr_iter = Q_Next(&el->attrs);
- }
-
- if (b_must_understand) {
-
- if (!actor || !strcmp(actor, TOKEN_ACTOR_NEXT)) {
-
- XMLRPC_RequestSetError(request,
- gen_soap_fault("SOAP-ENV:MustUnderstand",
- "SOAP Must Understand Error",
- "", ""));
- return xCurrent;
- }
- }
-
- if (id) {
- XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
- }
-
- if (depth == 3) {
- const char* methodname = el->name;
- char* p = NULL;
-
- 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);
-
- p = strchr(el->name, ':');
- if (p) {
- methodname = p + 1;
- }
- if (rtype == xmlrpc_request_call) {
- XMLRPC_RequestSetMethodName(request, methodname);
- }
- }
-
- 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)) {
-
- }
- 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);
- }
- }
-
- 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) {
-
- ai = parse_array_type_info(arrayType);
- XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
- }
- else {
-
- XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
- }
-
- while ( iter && !XMLRPC_RequestGetError(request) ) {
- XMLRPC_VALUE xNext = NULL;
-
- if ( depth <= 2 ||
- (rtype == xmlrpc_request_response && depth <= 3) ) {
- xml_element_to_SOAP_REQUEST_worker(request, NULL, ai, xCurrent, iter, depth);
- }
-
- 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);
- }
-
- if (ai) {
- free(ai);
- }
- }
- }
- return xCurrent;
- }
- XMLRPC_VALUE xml_element_to_SOAP_VALUE(xml_element* el)
- {
- return xml_element_to_SOAP_REQUEST_worker(NULL, NULL, NULL, NULL, el, 0);
- }
- 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;
- }
- 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;
- char buf[BUF_SIZE];
- XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(node);
- char* pName = NULL, *pAttrType = NULL;
-
- elem_val = xml_elem_new();
- switch (type) {
- case xmlrpc_type_struct:
- case xmlrpc_type_mixed:
- case xmlrpc_type_array:
- if (type == xmlrpc_type_array) {
-
-
- const char* type = get_array_soap_type(node);
- xml_element_attr* attr_array_type = NULL;
-
- 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;
- }
-
- else if (type == xmlrpc_type_struct) {
- int fault_type = get_fault_type(node);
- if (fault_type) {
- if (fault_type == 1) {
-
- node = gen_fault_xmlrpc(node, elem_val);
- bFreeNode = 1;
- }
- pName = TOKEN_FAULT;
- }
- }
- {
-
- 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;
-
- 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;
- }
-
- if (!pName) {
-
- if (pAttrType) {
-
- pName = (char*)XMLRPC_GetValueID(node);
- if (pName) {
- Q_PushTail(&elem_val->attrs, new_attr(TOKEN_TYPE, pAttrType));
- }
-
- else {
- pName = pAttrType;
- }
- }
-
- else {
-
- pName = (char*)XMLRPC_GetValueID(node);
- if (!pName) {
- pName = "item";
- }
- }
- }
- elem_val->name = strdup(pName);
-
- if (bFreeNode) {
- XMLRPC_CleanupValue(node);
- }
- }
- return elem_val;
- }
- xml_element* SOAP_VALUE_to_xml_element(XMLRPC_VALUE node) {
- return SOAP_to_xml_element_worker(NULL, node);
- }
- xml_element* SOAP_REQUEST_to_xml_element(XMLRPC_REQUEST request) {
- xml_element* root = xml_elem_new();
-
- if (root) {
- xml_element* body = xml_elem_new();
- root->name = strdup("SOAP-ENV:Envelope");
-
- 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/"));
-
- if (body) {
-
- xml_element* el_serialized =
- SOAP_to_xml_element_worker(request,
- XMLRPC_RequestGetData(request));
-
- if (el_serialized && !strcmp(el_serialized->name, TOKEN_FAULT)) {
- Q_PushTail(&body->children, el_serialized);
- }
-
- else {
- xml_element* rpc = xml_elem_new();
- if (rpc) {
- const char* methodname = XMLRPC_RequestGetMethodName(request);
- XMLRPC_REQUEST_TYPE rtype = XMLRPC_RequestGetRequestType(request);
-
- if (rtype == xmlrpc_request_call) {
- if (methodname) {
- rpc->name = strdup(methodname);
- }
- }
-
- else {
- char buf[128];
- snprintf(buf, sizeof(buf), "%s%s",
- methodname ? methodname : "",
- "Response");
- rpc->name = strdup(buf);
- }
-
- 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 {
-
- }
- }
- }
- body->name = strdup("SOAP-ENV:Body");
- Q_PushTail(&root->children, body);
- }
- }
- return root;
- }
|