Back to index

php5  5.3.10
xml_to_dandarpc.c
Go to the documentation of this file.
00001 /*
00002   This file is part of libXMLRPC - a C library for xml-encoded function calls.
00003 
00004   Author: Dan Libby (dan@libby.com)
00005   Epinions.com may be contacted at feedback@epinions-inc.com
00006 */
00007 
00008 /*  
00009   Copyright 2000 Epinions, Inc. 
00010 
00011   Subject to the following 3 conditions, Epinions, Inc.  permits you, free 
00012   of charge, to (a) use, copy, distribute, modify, perform and display this 
00013   software and associated documentation files (the "Software"), and (b) 
00014   permit others to whom the Software is furnished to do so as well.  
00015 
00016   1) The above copyright notice and this permission notice shall be included 
00017   without modification in all copies or substantial portions of the 
00018   Software.  
00019 
00020   2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF 
00021   ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY 
00022   IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR 
00023   PURPOSE OR NONINFRINGEMENT.  
00024 
00025   3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, 
00026   SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 
00027   OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING 
00028   NEGLIGENCE), EVEN IF EPINIONS, INC.  IS AWARE OF THE POSSIBILITY OF SUCH 
00029   DAMAGES.    
00030 
00031 */
00032 
00033 #ifdef _WIN32
00034 #include "xmlrpc_win32.h"
00035 #endif
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include "xml_to_dandarpc.h"
00039 #include "base64.h"
00040 
00041 /* list of tokens used in vocab */
00042 #define ELEM_METHODCALL     "methodCall"
00043 #define ELEM_METHODNAME     "methodName"
00044 #define ELEM_METHODRESPONSE "methodResponse"
00045 #define ELEM_ROOT           "simpleRPC"
00046 
00047 #define ATTR_ARRAY          "array"
00048 #define ATTR_BASE64         "base64"
00049 #define ATTR_BOOLEAN        "boolean"
00050 #define ATTR_DATETIME       "dateTime.iso8601"
00051 #define ATTR_DOUBLE         "double"
00052 #define ATTR_ID             "id"
00053 #define ATTR_INT            "int"
00054 #define ATTR_MIXED          "mixed"
00055 #define ATTR_SCALAR         "scalar"
00056 #define ATTR_STRING         "string"
00057 #define ATTR_STRUCT         "struct"
00058 #define ATTR_TYPE           "type"
00059 #define ATTR_VECTOR         "vector"
00060 #define ATTR_VERSION        "version"
00061 
00062 #define VAL_VERSION_0_9     "0.9"
00063 
00064 
00065 XMLRPC_VALUE xml_element_to_DANDARPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE xCurrent, xml_element* el) {
00066    if(!xCurrent) {
00067       xCurrent = XMLRPC_CreateValueEmpty();
00068    }
00069 
00070    if(el->name) {
00071       const char* id = NULL;
00072       const char* type = NULL;
00073       xml_element_attr* attr_iter = Q_Head(&el->attrs);
00074 
00075       while(attr_iter) {
00076          if(!strcmp(attr_iter->key, ATTR_ID)) {
00077             id = attr_iter->val;
00078          }
00079          if(!strcmp(attr_iter->key, ATTR_TYPE)) {
00080             type = attr_iter->val;
00081          }
00082          attr_iter = Q_Next(&el->attrs);
00083       }
00084 
00085       if(id) {
00086          XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
00087       }
00088 
00089       if(!strcmp(el->name, ATTR_SCALAR)) {
00090          if(!type || !strcmp(type, ATTR_STRING)) {
00091             XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
00092          }
00093          else if(!strcmp(type, ATTR_INT)) {
00094             XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
00095          }
00096          else if(!strcmp(type, ATTR_BOOLEAN)) {
00097             XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
00098          }
00099          else if(!strcmp(type, ATTR_DOUBLE)) {
00100             XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
00101          }
00102          else if(!strcmp(type, ATTR_DATETIME)) {
00103             XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
00104          }
00105          else if(!strcmp(type, ATTR_BASE64)) {
00106             struct buffer_st buf;
00107             base64_decode_xmlrpc(&buf, el->text.str, el->text.len);
00108             XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
00109             buffer_delete(&buf);
00110          }
00111       }
00112       else if(!strcmp(el->name, ATTR_VECTOR)) {
00113          xml_element* iter = (xml_element*)Q_Head(&el->children);
00114 
00115          if(!type || !strcmp(type, ATTR_MIXED)) {
00116             XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
00117          }
00118          else if(!strcmp(type, ATTR_ARRAY)) {
00119                             XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
00120          }
00121          else if(!strcmp(type, ATTR_STRUCT)) {
00122             XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
00123          }
00124          while( iter ) {
00125             XMLRPC_VALUE xNext = XMLRPC_CreateValueEmpty();
00126             xml_element_to_DANDARPC_REQUEST_worker(request, xNext, iter);
00127             XMLRPC_AddValueToVector(xCurrent, xNext);
00128             iter = (xml_element*)Q_Next(&el->children);
00129          }
00130       }
00131       else {
00132          xml_element* iter = (xml_element*)Q_Head(&el->children);
00133          while( iter ) {
00134             xml_element_to_DANDARPC_REQUEST_worker(request, xCurrent, iter);
00135             iter = (xml_element*)Q_Next(&el->children);
00136          }
00137 
00138          if(!strcmp(el->name, ELEM_METHODCALL)) {
00139             if(request) {
00140                XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
00141             }
00142          }
00143          else if(!strcmp(el->name, ELEM_METHODRESPONSE)) {
00144             if(request) {
00145                XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
00146             }
00147          }
00148          else if(!strcmp(el->name, ELEM_METHODNAME)) {
00149             if(request) {
00150                XMLRPC_RequestSetMethodName(request, el->text.str);
00151             }
00152          }
00153       }
00154    }
00155    return xCurrent;
00156 }
00157 
00158 XMLRPC_VALUE xml_element_to_DANDARPC_VALUE(xml_element* el)
00159 {
00160    return xml_element_to_DANDARPC_REQUEST_worker(NULL, NULL, el);
00161 }
00162 
00163 XMLRPC_VALUE xml_element_to_DANDARPC_REQUEST(XMLRPC_REQUEST request, xml_element* el)
00164 {
00165    if(request) {
00166       return XMLRPC_RequestSetData(request, xml_element_to_DANDARPC_REQUEST_worker(request, NULL, el));
00167    }
00168    return NULL;
00169 }
00170 
00171 xml_element* DANDARPC_to_xml_element_worker(XMLRPC_REQUEST request, XMLRPC_VALUE node) {
00172 #define BUF_SIZE 512
00173    xml_element* root = NULL;
00174    if(node) {
00175       char buf[BUF_SIZE];
00176       const char* id = XMLRPC_GetValueID(node);
00177       XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(node);
00178       XMLRPC_REQUEST_OUTPUT_OPTIONS output = XMLRPC_RequestGetOutputOptions(request);
00179       int bNoAddType = (type == xmlrpc_string && request && output && output->xml_elem_opts.verbosity == xml_elem_no_white_space);
00180       xml_element* elem_val = xml_elem_new();
00181       const char* pAttrType = NULL;
00182 
00183       xml_element_attr* attr_type = bNoAddType ? NULL : malloc(sizeof(xml_element_attr));
00184        
00185       if(attr_type) {
00186          attr_type->key = strdup(ATTR_TYPE);
00187          attr_type->val = 0;
00188          Q_PushTail(&elem_val->attrs, attr_type);
00189       }
00190 
00191       elem_val->name = (type == xmlrpc_vector) ? strdup(ATTR_VECTOR) : strdup(ATTR_SCALAR);
00192 
00193       if(id && *id) {
00194          xml_element_attr* attr_id = malloc(sizeof(xml_element_attr));
00195          if(attr_id) {
00196             attr_id->key = strdup(ATTR_ID);
00197             attr_id->val = strdup(id);
00198             Q_PushTail(&elem_val->attrs, attr_id);
00199          }
00200       }
00201 
00202       switch(type) {
00203          case xmlrpc_string:
00204             pAttrType = ATTR_STRING;
00205             simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node));
00206             break;
00207          case xmlrpc_int:
00208             pAttrType = ATTR_INT;
00209             snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node));
00210             simplestring_add(&elem_val->text, buf);
00211             break;
00212          case xmlrpc_boolean:
00213             pAttrType = ATTR_BOOLEAN;
00214             snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node));
00215             simplestring_add(&elem_val->text, buf);
00216             break;
00217          case xmlrpc_double:
00218             pAttrType = ATTR_DOUBLE;
00219             snprintf(buf, BUF_SIZE, "%f", XMLRPC_GetValueDouble(node));
00220             simplestring_add(&elem_val->text, buf);
00221             break;
00222          case xmlrpc_datetime:
00223             pAttrType = ATTR_DATETIME;
00224             simplestring_add(&elem_val->text, XMLRPC_GetValueDateTime_ISO8601(node));
00225             break;
00226          case xmlrpc_base64:
00227             {
00228                struct buffer_st buf;
00229                pAttrType = ATTR_BASE64;
00230                base64_encode_xmlrpc(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node));
00231                simplestring_addn(&elem_val->text, buf.data, buf.offset );
00232                buffer_delete(&buf);
00233             }
00234             break;
00235          case xmlrpc_vector:
00236             {
00237                XMLRPC_VECTOR_TYPE my_type = XMLRPC_GetVectorType(node);
00238                XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
00239 
00240                switch(my_type) {
00241                   case xmlrpc_vector_array:
00242                      pAttrType = ATTR_ARRAY;
00243                      break;
00244                   case xmlrpc_vector_mixed:
00245                      pAttrType = ATTR_MIXED;
00246                      break;
00247                   case xmlrpc_vector_struct:
00248                      pAttrType = ATTR_STRUCT;
00249                      break;
00250                   default:
00251                      break;
00252                }
00253 
00254                /* recurse through sub-elements */
00255                while( xIter ) {
00256                   xml_element* next_el = DANDARPC_to_xml_element_worker(request, xIter);
00257                   if(next_el) {
00258                      Q_PushTail(&elem_val->children, next_el);
00259                   }
00260                   xIter = XMLRPC_VectorNext(node);
00261                }
00262             }
00263             break;
00264          default:
00265             break;
00266       }
00267       if(pAttrType && attr_type && !bNoAddType) {
00268          attr_type->val = strdup(pAttrType);
00269       }
00270       root = elem_val;
00271    }
00272    return root;
00273 }
00274 
00275 xml_element* DANDARPC_VALUE_to_xml_element(XMLRPC_VALUE node) {
00276    return DANDARPC_to_xml_element_worker(NULL, node);
00277 }
00278 
00279 xml_element* DANDARPC_REQUEST_to_xml_element(XMLRPC_REQUEST request) {
00280    xml_element* wrapper = NULL;
00281    xml_element* root = NULL;
00282    if(request) {
00283       XMLRPC_REQUEST_TYPE request_type = XMLRPC_RequestGetRequestType(request);
00284       const char* pStr = NULL;
00285       xml_element_attr* version = malloc(sizeof(xml_element_attr));
00286       version->key = strdup(ATTR_VERSION);
00287       version->val = strdup(VAL_VERSION_0_9);
00288       
00289       wrapper = xml_elem_new();
00290 
00291       if(request_type == xmlrpc_request_response) {
00292          pStr = ELEM_METHODRESPONSE;
00293       }
00294       else if(request_type == xmlrpc_request_call) {
00295          pStr = ELEM_METHODCALL;
00296       }
00297       if(pStr) {
00298          wrapper->name = strdup(pStr);
00299       }
00300 
00301       root = xml_elem_new();
00302       root->name = strdup(ELEM_ROOT);
00303       Q_PushTail(&root->attrs, version);
00304       Q_PushTail(&root->children, wrapper);
00305 
00306       pStr = XMLRPC_RequestGetMethodName(request);
00307 
00308       if(pStr) {
00309          xml_element* method = xml_elem_new();
00310          method->name = strdup(ELEM_METHODNAME);
00311          simplestring_add(&method->text, pStr);
00312          Q_PushTail(&wrapper->children, method);
00313       }
00314       Q_PushTail(&wrapper->children, 
00315                  DANDARPC_to_xml_element_worker(request, XMLRPC_RequestGetData(request)));
00316    }
00317    return root;
00318 }
00319