Annotation of embedaddon/php/ext/xmlrpc/libxmlrpc/xml_to_xmlrpc.c, revision 1.1

1.1     ! misho       1: /*
        !             2:   This file is part of libXMLRPC - a C library for xml-encoded function calls.
        !             3: 
        !             4:   Author: Dan Libby (dan@libby.com)
        !             5:   Epinions.com may be contacted at feedback@epinions-inc.com
        !             6: */
        !             7: 
        !             8: /*  
        !             9:   Copyright 2000 Epinions, Inc. 
        !            10: 
        !            11:   Subject to the following 3 conditions, Epinions, Inc.  permits you, free 
        !            12:   of charge, to (a) use, copy, distribute, modify, perform and display this 
        !            13:   software and associated documentation files (the "Software"), and (b) 
        !            14:   permit others to whom the Software is furnished to do so as well.  
        !            15: 
        !            16:   1) The above copyright notice and this permission notice shall be included 
        !            17:   without modification in all copies or substantial portions of the 
        !            18:   Software.  
        !            19: 
        !            20:   2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF 
        !            21:   ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY 
        !            22:   IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR 
        !            23:   PURPOSE OR NONINFRINGEMENT.  
        !            24: 
        !            25:   3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, 
        !            26:   SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 
        !            27:   OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING 
        !            28:   NEGLIGENCE), EVEN IF EPINIONS, INC.  IS AWARE OF THE POSSIBILITY OF SUCH 
        !            29:   DAMAGES.    
        !            30: 
        !            31: */
        !            32: 
        !            33: 
        !            34: static const char rcsid[] = "#(@) $Id: xml_to_xmlrpc.c 242949 2007-09-26 15:44:16Z cvs2svn $";
        !            35: 
        !            36: #include "php.h"
        !            37: #include "main/snprintf.h"
        !            38: #ifdef _WIN32
        !            39: #include "xmlrpc_win32.h"
        !            40: #endif
        !            41: #include <string.h>
        !            42: #include <stdlib.h>
        !            43: #include "xml_to_xmlrpc.h"
        !            44: #include "base64.h"
        !            45: 
        !            46: /* list of tokens used in vocab */
        !            47: #define ELEM_ARRAY          "array"
        !            48: #define ELEM_BASE64         "base64"
        !            49: #define ELEM_BOOLEAN        "boolean"
        !            50: #define ELEM_DATA           "data"
        !            51: #define ELEM_DATETIME       "dateTime.iso8601"
        !            52: #define ELEM_DOUBLE         "double"
        !            53: #define ELEM_FAULT          "fault"
        !            54: #define ELEM_FAULTCODE      "faultCode"
        !            55: #define ELEM_FAULTSTRING    "faultString"
        !            56: #define ELEM_I4             "i4"
        !            57: #define ELEM_INT            "int"
        !            58: #define ELEM_MEMBER         "member"
        !            59: #define ELEM_METHODCALL     "methodCall"
        !            60: #define ELEM_METHODNAME     "methodName"
        !            61: #define ELEM_METHODRESPONSE "methodResponse"
        !            62: #define ELEM_NAME           "name"
        !            63: #define ELEM_PARAM          "param"
        !            64: #define ELEM_PARAMS         "params"
        !            65: #define ELEM_STRING         "string"
        !            66: #define ELEM_STRUCT         "struct"
        !            67: #define ELEM_VALUE          "value"
        !            68: 
        !            69: 
        !            70: XMLRPC_VALUE xml_element_to_XMLRPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE parent_vector, XMLRPC_VALUE current_val, xml_element* el) {
        !            71:    if (!current_val) {
        !            72:       /* This should only be the case for the first element */
        !            73:       current_val = XMLRPC_CreateValueEmpty();
        !            74:    }
        !            75: 
        !            76:        if (el->name) {
        !            77: 
        !            78:       /* first, deal with the crazy/stupid fault format */
        !            79:       if (!strcmp(el->name, ELEM_FAULT)) {
        !            80:                        xml_element* fault_value = (xml_element*)Q_Head(&el->children);
        !            81:                        XMLRPC_SetIsVector(current_val, xmlrpc_vector_struct);
        !            82: 
        !            83:          if(fault_value) {
        !            84:             xml_element* fault_struct = (xml_element*)Q_Head(&fault_value->children);
        !            85:             if(fault_struct) {
        !            86:                xml_element* iter = (xml_element*)Q_Head(&fault_struct->children);
        !            87: 
        !            88:                while (iter) {
        !            89:                   XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
        !            90:                   xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
        !            91:                   XMLRPC_AddValueToVector(current_val, xNextVal);
        !            92:                   iter = (xml_element*)Q_Next(&fault_struct->children);
        !            93:                }
        !            94:             }
        !            95:          }
        !            96:       }
        !            97:                else if (!strcmp(el->name, ELEM_DATA)   /* should be ELEM_ARRAY, but there is an extra level. weird */
        !            98:                         || (!strcmp(el->name, ELEM_PARAMS) && 
        !            99:                                  (XMLRPC_RequestGetRequestType(request) == xmlrpc_request_call)) ) {           /* this "PARAMS" concept is silly.  dave?! */
        !           100:          xml_element* iter = (xml_element*)Q_Head(&el->children);
        !           101:          XMLRPC_SetIsVector(current_val, xmlrpc_vector_array);
        !           102: 
        !           103:          while (iter) {
        !           104:             XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
        !           105:             xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
        !           106:             XMLRPC_AddValueToVector(current_val, xNextVal);
        !           107:             iter = (xml_element*)Q_Next(&el->children);
        !           108:          }
        !           109:                }
        !           110:                else if (!strcmp(el->name, ELEM_STRUCT)) {
        !           111:          xml_element* iter = (xml_element*)Q_Head(&el->children);
        !           112:          XMLRPC_SetIsVector(current_val, xmlrpc_vector_struct);
        !           113: 
        !           114:          while ( iter ) {
        !           115:             XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
        !           116:             xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
        !           117:             XMLRPC_AddValueToVector(current_val, xNextVal);
        !           118:             iter = (xml_element*)Q_Next(&el->children);
        !           119:          }
        !           120:                }
        !           121:                else if (!strcmp(el->name, ELEM_STRING) || 
        !           122:                  (!strcmp(el->name, ELEM_VALUE) && Q_Size(&el->children) == 0)) {
        !           123:          XMLRPC_SetValueString(current_val, el->text.str, el->text.len);
        !           124:                }
        !           125:                else if (!strcmp(el->name, ELEM_NAME)) {
        !           126:          XMLRPC_SetValueID_Case(current_val, el->text.str, 0, xmlrpc_case_exact);
        !           127:                }
        !           128:                else if (!strcmp(el->name, ELEM_INT) || !strcmp(el->name, ELEM_I4)) {
        !           129:          XMLRPC_SetValueInt(current_val, atoi(el->text.str));
        !           130:                }
        !           131:                else if (!strcmp(el->name, ELEM_BOOLEAN)) {
        !           132:          XMLRPC_SetValueBoolean(current_val, atoi(el->text.str));
        !           133:                }
        !           134:                else if (!strcmp(el->name, ELEM_DOUBLE)) {
        !           135:          XMLRPC_SetValueDouble(current_val, atof(el->text.str));
        !           136:                }
        !           137:                else if (!strcmp(el->name, ELEM_DATETIME)) {
        !           138:          XMLRPC_SetValueDateTime_ISO8601(current_val, el->text.str);
        !           139:                }
        !           140:                else if (!strcmp(el->name, ELEM_BASE64)) {
        !           141:          struct buffer_st buf;
        !           142:          base64_decode_xmlrpc(&buf, el->text.str, el->text.len);
        !           143:          XMLRPC_SetValueBase64(current_val, buf.data, buf.offset);
        !           144:          buffer_delete(&buf);
        !           145:                }
        !           146:                else {
        !           147:          xml_element* iter;
        !           148: 
        !           149:          if (!strcmp(el->name, ELEM_METHODCALL)) {
        !           150:             if (request) {
        !           151:                XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
        !           152:             }
        !           153:                        }
        !           154:                        else if (!strcmp(el->name, ELEM_METHODRESPONSE)) {
        !           155:             if (request) {
        !           156:                XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
        !           157:             }
        !           158:                        }
        !           159:                        else if (!strcmp(el->name, ELEM_METHODNAME)) {
        !           160:             if (request) {
        !           161:                XMLRPC_RequestSetMethodName(request, el->text.str);
        !           162:             }
        !           163:          }
        !           164: 
        !           165:          iter = (xml_element*)Q_Head(&el->children);
        !           166:          while ( iter ) {
        !           167:             xml_element_to_XMLRPC_REQUEST_worker(request, parent_vector, 
        !           168:                                                  current_val, iter);
        !           169:             iter = (xml_element*)Q_Next(&el->children);
        !           170:          }
        !           171:       }
        !           172:    }
        !           173:    return current_val;
        !           174: }
        !           175: 
        !           176: XMLRPC_VALUE xml_element_to_XMLRPC_VALUE(xml_element* el)
        !           177: {
        !           178:    return xml_element_to_XMLRPC_REQUEST_worker(NULL, NULL, NULL, el);
        !           179: }
        !           180: 
        !           181: XMLRPC_VALUE xml_element_to_XMLRPC_REQUEST(XMLRPC_REQUEST request, xml_element* el)
        !           182: {
        !           183:    if (request) {
        !           184:       return XMLRPC_RequestSetData(request, xml_element_to_XMLRPC_REQUEST_worker(request, NULL, NULL, el));
        !           185:    }
        !           186:    return NULL;
        !           187: }
        !           188: 
        !           189: xml_element* XMLRPC_to_xml_element_worker(XMLRPC_VALUE current_vector, XMLRPC_VALUE node, 
        !           190:                                           XMLRPC_REQUEST_TYPE request_type, int depth) {
        !           191: #define BUF_SIZE 512
        !           192:    xml_element* root = NULL;
        !           193:    if (node) {
        !           194:       char buf[BUF_SIZE];
        !           195:       XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(node);
        !           196:       XMLRPC_VECTOR_TYPE vtype = XMLRPC_GetVectorType(node);
        !           197:       xml_element* elem_val = xml_elem_new();
        !           198: 
        !           199:       /* special case for when root element is not an array */
        !           200:       if (depth == 0 && 
        !           201:           !(type == xmlrpc_vector && 
        !           202:             vtype == xmlrpc_vector_array && 
        !           203:             request_type == xmlrpc_request_call) ) {
        !           204:          int bIsFault = (vtype == xmlrpc_vector_struct && XMLRPC_VectorGetValueWithID(node, ELEM_FAULTCODE));
        !           205: 
        !           206:          xml_element* next_el = XMLRPC_to_xml_element_worker(NULL, node, request_type, depth + 1);
        !           207:          if (next_el) {
        !           208:             Q_PushTail(&elem_val->children, next_el);
        !           209:          }
        !           210:          elem_val->name = strdup(bIsFault ? ELEM_FAULT : ELEM_PARAMS);
        !           211:                }
        !           212:                else {
        !           213:          switch (type) {
        !           214:                        case xmlrpc_empty: /*  treat null value as empty string in xmlrpc. */
        !           215:          case xmlrpc_string:
        !           216:             elem_val->name = strdup(ELEM_STRING);
        !           217:             simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node));
        !           218:             break;
        !           219:          case xmlrpc_int:
        !           220:             elem_val->name = strdup(ELEM_INT);
        !           221:             snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node));
        !           222:             simplestring_add(&elem_val->text, buf);
        !           223:             break;
        !           224:          case xmlrpc_boolean:
        !           225:             elem_val->name = strdup(ELEM_BOOLEAN);
        !           226:             snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node));
        !           227:             simplestring_add(&elem_val->text, buf);
        !           228:             break;
        !           229:          case xmlrpc_double:
        !           230:             {
        !           231:                 TSRMLS_FETCH();
        !           232:                 elem_val->name = strdup(ELEM_DOUBLE);
        !           233:                 ap_php_snprintf(buf, BUF_SIZE, "%.*G", (int) EG(precision), XMLRPC_GetValueDouble(node));
        !           234:                 simplestring_add(&elem_val->text, buf);
        !           235:             }
        !           236:             break;
        !           237:          case xmlrpc_datetime:
        !           238:             elem_val->name = strdup(ELEM_DATETIME);
        !           239:             simplestring_add(&elem_val->text, XMLRPC_GetValueDateTime_ISO8601(node));
        !           240:             break;
        !           241:          case xmlrpc_base64:
        !           242:             {
        !           243:                struct buffer_st buf;
        !           244:                elem_val->name = strdup(ELEM_BASE64);
        !           245:                base64_encode_xmlrpc(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node));
        !           246:                simplestring_addn(&elem_val->text, buf.data, buf.offset );
        !           247:                buffer_delete(&buf);
        !           248:             }
        !           249:             break;
        !           250:          case xmlrpc_vector:
        !           251:             {
        !           252:                XMLRPC_VECTOR_TYPE my_type = XMLRPC_GetVectorType(node);
        !           253:                XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
        !           254:                xml_element* root_vector_elem = elem_val;
        !           255: 
        !           256:                switch (my_type) {
        !           257:                case xmlrpc_vector_array:
        !           258:                   {
        !           259:                       if(depth == 0) {
        !           260:                          elem_val->name = strdup(ELEM_PARAMS);
        !           261:                       }
        !           262:                       else {
        !           263:                          /* Hi my name is Dave and I like to make things as confusing
        !           264:                           * as possible, thus I will throw in this 'data' element
        !           265:                           * where it absolutely does not belong just so that people
        !           266:                           * cannot code arrays and structs in a similar and straight
        !           267:                           * forward manner. Have a good day.
        !           268:                           *
        !           269:                           * GRRRRRRRRR!
        !           270:                           */
        !           271:                          xml_element* data = xml_elem_new();
        !           272:                          data->name = strdup(ELEM_DATA);
        !           273:     
        !           274:                          elem_val->name = strdup(ELEM_ARRAY);
        !           275:                          Q_PushTail(&elem_val->children, data);
        !           276:                          root_vector_elem = data;
        !           277:                       }
        !           278:                   }
        !           279:                   break;
        !           280:                case xmlrpc_vector_mixed:       /* not officially supported */
        !           281:                case xmlrpc_vector_struct:
        !           282:                   elem_val->name = strdup(ELEM_STRUCT);
        !           283:                   break;
        !           284:                default:
        !           285:                   break;
        !           286:                }
        !           287: 
        !           288:                /* recurse through sub-elements */
        !           289:                while ( xIter ) {
        !           290:                   xml_element* next_el = XMLRPC_to_xml_element_worker(node, xIter, request_type, depth + 1);
        !           291:                   if (next_el) {
        !           292:                      Q_PushTail(&root_vector_elem->children, next_el);
        !           293:                   }
        !           294:                   xIter = XMLRPC_VectorNext(node);
        !           295:                }
        !           296:             }
        !           297:             break;
        !           298:          default:
        !           299:             break;
        !           300:          }
        !           301:       }
        !           302: 
        !           303:       {
        !           304:          XMLRPC_VECTOR_TYPE vtype = XMLRPC_GetVectorType(current_vector);
        !           305: 
        !           306:          if (depth == 1) {
        !           307:             xml_element* value = xml_elem_new();
        !           308:             value->name = strdup(ELEM_VALUE);
        !           309: 
        !           310:             /* yet another hack for the "fault" crap */
        !           311:             if (XMLRPC_VectorGetValueWithID(node, ELEM_FAULTCODE)) {
        !           312:                root = value;
        !           313:                                }
        !           314:                                else {
        !           315:                xml_element* param = xml_elem_new();
        !           316:                param->name = strdup(ELEM_PARAM);
        !           317: 
        !           318:                Q_PushTail(&param->children, value);
        !           319: 
        !           320:                root = param;
        !           321:             }
        !           322:             Q_PushTail(&value->children, elem_val);
        !           323:                        }
        !           324:                        else if (vtype == xmlrpc_vector_struct || vtype == xmlrpc_vector_mixed) {
        !           325:             xml_element* member = xml_elem_new();
        !           326:             xml_element* name = xml_elem_new();
        !           327:             xml_element* value = xml_elem_new();
        !           328: 
        !           329:             member->name = strdup(ELEM_MEMBER);
        !           330:             name->name = strdup(ELEM_NAME);
        !           331:             value->name = strdup(ELEM_VALUE);
        !           332: 
        !           333:             simplestring_add(&name->text, XMLRPC_GetValueID(node));
        !           334: 
        !           335:             Q_PushTail(&member->children, name);
        !           336:             Q_PushTail(&member->children, value);
        !           337:             Q_PushTail(&value->children, elem_val);
        !           338: 
        !           339:             root = member;
        !           340:                        }
        !           341:                        else if (vtype == xmlrpc_vector_array) {
        !           342:             xml_element* value = xml_elem_new();
        !           343: 
        !           344:             value->name = strdup(ELEM_VALUE);
        !           345: 
        !           346:             Q_PushTail(&value->children, elem_val);
        !           347: 
        !           348:             root = value;
        !           349:                        }
        !           350:                        else if (vtype == xmlrpc_vector_none) {
        !           351:             /* no parent.  non-op */
        !           352:             root = elem_val;
        !           353:                        }
        !           354:                        else {
        !           355:             xml_element* value = xml_elem_new();
        !           356: 
        !           357:             value->name = strdup(ELEM_VALUE);
        !           358: 
        !           359:             Q_PushTail(&value->children, elem_val);
        !           360: 
        !           361:             root = value;
        !           362:          }
        !           363:       }
        !           364:    }
        !           365:    return root;
        !           366: }
        !           367: 
        !           368: xml_element* XMLRPC_VALUE_to_xml_element(XMLRPC_VALUE node) {
        !           369:    return XMLRPC_to_xml_element_worker(NULL, node, xmlrpc_request_none, 0);
        !           370: }
        !           371: 
        !           372: xml_element* XMLRPC_REQUEST_to_xml_element(XMLRPC_REQUEST request) {
        !           373:    xml_element* wrapper = NULL;
        !           374:    if (request) {
        !           375:       const char* pStr = NULL;
        !           376:       XMLRPC_REQUEST_TYPE request_type = XMLRPC_RequestGetRequestType(request);
        !           377:       XMLRPC_VALUE xParams = XMLRPC_RequestGetData(request);
        !           378: 
        !           379:       wrapper = xml_elem_new();
        !           380: 
        !           381:       if (request_type == xmlrpc_request_call) {
        !           382:          pStr = ELEM_METHODCALL;
        !           383:                }
        !           384:                else if (request_type == xmlrpc_request_response) {
        !           385:          pStr = ELEM_METHODRESPONSE;
        !           386:       }
        !           387:       if (pStr) {
        !           388:          wrapper->name = strdup(pStr);
        !           389:       }
        !           390: 
        !           391:                if(request_type == xmlrpc_request_call) {
        !           392:       pStr = XMLRPC_RequestGetMethodName(request);
        !           393: 
        !           394:       if (pStr) {
        !           395:          xml_element* method = xml_elem_new();
        !           396:          method->name = strdup(ELEM_METHODNAME);
        !           397:          simplestring_add(&method->text, pStr);
        !           398:          Q_PushTail(&wrapper->children, method);
        !           399:       }
        !           400:                }
        !           401:       if (xParams) {
        !           402:          Q_PushTail(&wrapper->children, 
        !           403:                     XMLRPC_to_xml_element_worker(NULL, XMLRPC_RequestGetData(request), XMLRPC_RequestGetRequestType(request), 0));
        !           404:                }
        !           405:                else {
        !           406:          /* Despite the spec, the xml-rpc list folk want me to send an empty params element */
        !           407:          xml_element* params = xml_elem_new();
        !           408:          params->name = strdup(ELEM_PARAMS);
        !           409:          Q_PushTail(&wrapper->children, params);
        !           410:       }
        !           411:    }
        !           412:    return wrapper;
        !           413: }
        !           414: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>