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(¶m->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>