Annotation of embedaddon/libpdel/structs/structs_xmlrpc.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42: #include <net/ethernet.h>
! 43:
! 44: #include <stdlib.h>
! 45: #include <stddef.h>
! 46: #include <stdio.h>
! 47: #include <stdarg.h>
! 48: #include <assert.h>
! 49: #include <ctype.h>
! 50: #include <syslog.h>
! 51: #include <string.h>
! 52: #include <errno.h>
! 53:
! 54: #include "structs/structs.h"
! 55: #include "structs/type/array.h"
! 56: #include "structs/type/struct.h"
! 57: #include "structs/type/union.h"
! 58: #include "structs/type/string.h"
! 59: #include "structs/type/float.h"
! 60: #include "structs/type/boolean.h"
! 61: #include "structs/type/data.h"
! 62: #include "structs/type/time.h"
! 63: #include "structs/type/int.h"
! 64: #include "structs/xml.h"
! 65: #include "structs/xmlrpc.h"
! 66: #include "util/typed_mem.h"
! 67:
! 68: /************************************************************************
! 69: string
! 70: ************************************************************************/
! 71:
! 72: static const struct structs_type string_type
! 73: = STRUCTS_STRING_TYPE("xmlrpc_string", 0);
! 74:
! 75: /************************************************************************
! 76: base64
! 77: ************************************************************************/
! 78:
! 79: static const struct structs_type base64_type
! 80: = STRUCTS_DATA_TYPE(NULL, "xmlrpc_base64");
! 81:
! 82: /************************************************************************
! 83: array data
! 84: ************************************************************************/
! 85:
! 86: static const struct structs_type array_data_type
! 87: = STRUCTS_ARRAY_TYPE(&structs_type_xmlrpc_value,
! 88: "xmlrpc_array", "value");
! 89:
! 90: /************************************************************************
! 91: array
! 92: ************************************************************************/
! 93:
! 94: static const struct structs_field array_fields[] = {
! 95: STRUCTS_STRUCT_FIELD(xmlrpc_array, data, &array_data_type),
! 96: STRUCTS_STRUCT_FIELD_END
! 97: };
! 98: const struct structs_type structs_type_xmlrpc_array
! 99: = STRUCTS_STRUCT_TYPE(xmlrpc_array, &array_fields);
! 100:
! 101: /************************************************************************
! 102: member
! 103: ************************************************************************/
! 104:
! 105: static const struct structs_field member_fields[] = {
! 106: STRUCTS_STRUCT_FIELD(xmlrpc_member, name, &string_type),
! 107: STRUCTS_STRUCT_FIELD(xmlrpc_member, value, &structs_type_xmlrpc_value),
! 108: STRUCTS_STRUCT_FIELD_END
! 109: };
! 110: const struct structs_type structs_type_xmlrpc_member
! 111: = STRUCTS_STRUCT_TYPE(xmlrpc_member, &member_fields);
! 112:
! 113: /************************************************************************
! 114: struct
! 115: ************************************************************************/
! 116:
! 117: const struct structs_type structs_type_xmlrpc_struct
! 118: = STRUCTS_ARRAY_TYPE(&structs_type_xmlrpc_member,
! 119: "xmlrpc_struct", "member");
! 120:
! 121: /************************************************************************
! 122: value
! 123: ************************************************************************/
! 124:
! 125: static const struct structs_ufield value_fields[] = {
! 126: STRUCTS_UNION_FIELD(string, &string_type),
! 127: STRUCTS_UNION_FIELD(i4, &structs_type_int32),
! 128: STRUCTS_UNION_FIELD(int, &structs_type_int32),
! 129: STRUCTS_UNION_FIELD(boolean, &structs_type_boolean_char_01),
! 130: STRUCTS_UNION_FIELD(double, &structs_type_double),
! 131: STRUCTS_UNION_FIELD(dateTime.iso8601, &structs_type_time_iso8601),
! 132: STRUCTS_UNION_FIELD(base64, &base64_type),
! 133: STRUCTS_UNION_FIELD(struct, &structs_type_xmlrpc_struct),
! 134: STRUCTS_UNION_FIELD(array, &structs_type_xmlrpc_array),
! 135: STRUCTS_UNION_FIELD_END
! 136: };
! 137: const struct structs_type structs_type_xmlrpc_value
! 138: = STRUCTS_UNION_TYPE(xmlrpc_value, &value_fields);
! 139:
! 140: /************************************************************************
! 141: param
! 142: ************************************************************************/
! 143:
! 144: static const struct structs_field param_fields[] = {
! 145: STRUCTS_STRUCT_FIELD(xmlrpc_param, value, &structs_type_xmlrpc_value),
! 146: STRUCTS_STRUCT_FIELD_END
! 147: };
! 148: static const struct structs_type param_type
! 149: = STRUCTS_STRUCT_TYPE(xmlrpc_param, ¶m_fields);
! 150:
! 151: /************************************************************************
! 152: params
! 153: ************************************************************************/
! 154:
! 155: static const struct structs_type params_type
! 156: = STRUCTS_ARRAY_TYPE(¶m_type, "xmlrpc_params", "param");
! 157:
! 158: /************************************************************************
! 159: fault
! 160: ************************************************************************/
! 161:
! 162: static const struct structs_field fault_fields[] = {
! 163: STRUCTS_STRUCT_FIELD(xmlrpc_fault, value, &structs_type_xmlrpc_value),
! 164: STRUCTS_STRUCT_FIELD_END
! 165: };
! 166: const struct structs_type structs_type_xmlrpc_fault
! 167: = STRUCTS_STRUCT_TYPE(xmlrpc_fault, &fault_fields);
! 168:
! 169: /************************************************************************
! 170: request
! 171: ************************************************************************/
! 172:
! 173: static const struct structs_field request_fields[] = {
! 174: STRUCTS_STRUCT_FIELD(xmlrpc_request, methodName, &string_type),
! 175: STRUCTS_STRUCT_FIELD(xmlrpc_request, params, ¶ms_type),
! 176: STRUCTS_STRUCT_FIELD_END
! 177: };
! 178: const struct structs_type structs_type_xmlrpc_request
! 179: = STRUCTS_STRUCT_TYPE(xmlrpc_request, &request_fields);
! 180:
! 181: /************************************************************************
! 182: response
! 183: ************************************************************************/
! 184:
! 185: static const struct structs_ufield response_fields[] = {
! 186: STRUCTS_UNION_FIELD(params, ¶ms_type),
! 187: STRUCTS_UNION_FIELD(fault, &structs_type_xmlrpc_fault),
! 188: STRUCTS_UNION_FIELD_END
! 189: };
! 190: const struct structs_type structs_type_xmlrpc_response
! 191: = STRUCTS_UNION_TYPE(xmlrpc_response, &response_fields);
! 192:
! 193: /************************************************************************
! 194: fault (compact form)
! 195: ************************************************************************/
! 196:
! 197: static const struct structs_type fault_string_type
! 198: = STRUCTS_STRING_TYPE("xmlrpc_fault_string", 0);
! 199:
! 200: static const struct structs_field compact_fault_fields[] = {
! 201: STRUCTS_STRUCT_FIELD(xmlrpc_compact_fault,
! 202: faultCode, &structs_type_int32),
! 203: STRUCTS_STRUCT_FIELD(xmlrpc_compact_fault,
! 204: faultString, &fault_string_type),
! 205: STRUCTS_STRUCT_FIELD_END
! 206: };
! 207: const struct structs_type structs_type_xmlrpc_compact_fault
! 208: = STRUCTS_STRUCT_TYPE(xmlrpc_compact_fault, &compact_fault_fields);
! 209:
! 210: /************************************************************************
! 211: FUNCTIONS
! 212: ************************************************************************/
! 213:
! 214: /*
! 215: * Create an XML-RPC request structure with the given parameters.
! 216: */
! 217: struct xmlrpc_request *
! 218: structs_xmlrpc_build_request(const char *mtype, const char *methodName,
! 219: u_int nparams, const struct structs_type **types, const void **datas)
! 220: {
! 221: const struct structs_type *const xtype = &structs_type_xmlrpc_request;
! 222: struct xmlrpc_request *xreq;
! 223: u_int i;
! 224:
! 225: /* Create new XML-RPC request structure */
! 226: if ((xreq = MALLOC(mtype, sizeof(*xreq))) == NULL)
! 227: return (NULL);
! 228: if (structs_init(xtype, NULL, xreq) == -1) {
! 229: FREE(mtype, xreq);
! 230: return (NULL);
! 231: }
! 232:
! 233: /* Set method name */
! 234: if (structs_set_string(xtype,
! 235: "methodName", methodName, xreq, NULL, 0) == -1)
! 236: goto fail;
! 237:
! 238: /* Copy parameters into request */
! 239: for (i = 0; i < nparams; i++) {
! 240: const void *const data = datas[i];
! 241: char xname[32];
! 242:
! 243: /* Add another element to params array */
! 244: if (structs_array_insert(xtype, "params", i, xreq) == -1)
! 245: goto fail;
! 246: snprintf(xname, sizeof(xname), "params.%u.value", i);
! 247:
! 248: /* Explode parameter unless already exploded */
! 249: if (types != NULL) {
! 250: if (structs_struct2xmlrpc(types[i], data, NULL,
! 251: xtype, xreq, xname) == -1)
! 252: goto fail;
! 253: } else {
! 254: if (structs_set(&structs_type_xmlrpc_value,
! 255: data, xname, xreq) == -1)
! 256: goto fail;
! 257: }
! 258: }
! 259:
! 260: /* Done */
! 261: return (xreq);
! 262:
! 263: fail:
! 264: structs_free(xtype, NULL, xreq);
! 265: FREE(mtype, xreq);
! 266: return (NULL);
! 267: }
! 268:
! 269: /*
! 270: * Create an XML-RPC response structure with the given return value.
! 271: */
! 272: struct xmlrpc_response_union *
! 273: structs_xmlrpc_build_response(const char *mtype,
! 274: const struct structs_type *type, const void *data)
! 275: {
! 276: const struct structs_type *const xtype = &structs_type_xmlrpc_response;
! 277: struct xmlrpc_response_union *xrep;
! 278:
! 279: /* Create new XML-RPC response structure */
! 280: if ((xrep = MALLOC(mtype, sizeof(*xrep))) == NULL)
! 281: return (NULL);
! 282: if (structs_init(xtype, NULL, xrep) == -1) {
! 283: FREE(mtype, xrep);
! 284: return (NULL);
! 285: }
! 286:
! 287: /* Add a single parameter */
! 288: if (structs_array_insert(xtype, "params", 0, xrep) == -1)
! 289: goto fail;
! 290:
! 291: /* Copy parameter, optionally compacting it */
! 292: if (type != NULL) {
! 293: if (structs_struct2xmlrpc(type, data,
! 294: NULL, xtype, xrep, "params.0.value") == -1)
! 295: goto fail;
! 296: } else {
! 297: if (structs_set(&structs_type_xmlrpc_value,
! 298: data, "params.0.value", xrep) == -1)
! 299: goto fail;
! 300: }
! 301:
! 302: /* Done */
! 303: return (xrep);
! 304:
! 305: fail:
! 306: structs_free(xtype, NULL, xrep);
! 307: FREE(mtype, xrep);
! 308: return (NULL);
! 309: }
! 310:
! 311: /*
! 312: * Create an XML-RPC fault response structure with the given fault.
! 313: */
! 314: struct xmlrpc_response_union *
! 315: structs_xmlrpc_build_fault_response(const char *mtype,
! 316: const struct xmlrpc_compact_fault *fault)
! 317: {
! 318: const struct structs_type *const xtype = &structs_type_xmlrpc_response;
! 319: struct xmlrpc_response_union *xrep;
! 320:
! 321: /* Create new XML-RPC response structure */
! 322: if ((xrep = MALLOC(mtype, sizeof(*xrep))) == NULL)
! 323: return (NULL);
! 324: if (structs_init(xtype, NULL, xrep) == -1) {
! 325: FREE(mtype, xrep);
! 326: return (NULL);
! 327: }
! 328:
! 329: /* Set fault */
! 330: if (structs_struct2xmlrpc(&structs_type_xmlrpc_compact_fault,
! 331: fault, NULL, xtype, xrep, "fault.value") == -1)
! 332: goto fail;
! 333:
! 334: /* Done */
! 335: return (xrep);
! 336:
! 337: fail:
! 338: structs_free(xtype, NULL, xrep);
! 339: FREE(mtype, xrep);
! 340: return (NULL);
! 341: }
! 342:
! 343: /*
! 344: * Copy the contents of a normal structure into an XML-RPC "value" structure.
! 345: */
! 346: int
! 347: structs_struct2xmlrpc(const struct structs_type *type,
! 348: const void *data, const char *sname,
! 349: const struct structs_type *xtype, void *xdata, const char *xname)
! 350: {
! 351:
! 352: /* Find source and dest data */
! 353: if ((type = structs_find(type, sname, (void **)&data, 0)) == NULL)
! 354: return (-1);
! 355: if ((xtype = structs_find(xtype, xname, &xdata, 1)) == NULL)
! 356: return (-1);
! 357:
! 358: /* Destination type must always be an XML-RPC value */
! 359: if (xtype != &structs_type_xmlrpc_value) {
! 360: errno = EINVAL;
! 361: return (-1);
! 362: }
! 363:
! 364: /* Dereference through pointer(s) */
! 365: while (type->tclass == STRUCTS_TYPE_POINTER) {
! 366: type = type->args[0].v;
! 367: data = *((void **)data);
! 368: }
! 369:
! 370: switch (type->tclass) {
! 371: case STRUCTS_TYPE_PRIMITIVE:
! 372: {
! 373: const char *xprim;
! 374: char *s;
! 375:
! 376: /* Get corresponding XML-RPC primitive type */
! 377: if (type == &structs_type_int32
! 378: || (sizeof(int) == 4 && type == &structs_type_int))
! 379: xprim = "i4";
! 380: else if (strcmp(type->name, "float") == 0
! 381: || strcmp(type->name, "double") == 0)
! 382: xprim = "double";
! 383: else if (strcmp(type->name, "boolean") == 0)
! 384: xprim = "boolean";
! 385: else if (type == &structs_type_time_iso8601)
! 386: xprim = "dateTime.iso8601";
! 387: else if (strcmp(type->name, "data") == 0
! 388: && type->args[0].v == NULL) /* XXX same charmap */
! 389: xprim = "base64";
! 390: else
! 391: xprim = "string";
! 392:
! 393: /* Get primitive value as a string */
! 394: if ((s = structs_get_string(type,
! 395: NULL, data, TYPED_MEM_TEMP)) == NULL)
! 396: return (-1);
! 397:
! 398: /* Set primitive value as a string */
! 399: if (structs_set_string(xtype,
! 400: xprim, s, xdata, NULL, 0) == -1) {
! 401: FREE(TYPED_MEM_TEMP, s);
! 402: return (-1);
! 403: }
! 404: FREE(TYPED_MEM_TEMP, s);
! 405: break;
! 406: }
! 407: case STRUCTS_TYPE_ARRAY:
! 408: {
! 409: const struct structs_type *const etype = type->args[0].v;
! 410: const struct structs_array *const ary = data;
! 411: u_int i;
! 412:
! 413: /* Reset destination value to be an empty array */
! 414: if (structs_array_reset(xtype, "array.data", xdata) == -1)
! 415: return (-1);
! 416:
! 417: /* Copy over each element in the array */
! 418: for (i = 0; i < ary->length; i++) {
! 419: char buf[32];
! 420:
! 421: /* Add a new element to the dest array */
! 422: if (structs_array_insert(xtype,
! 423: "array.data", i, xdata) == -1)
! 424: return (-1);
! 425:
! 426: /* Set its value */
! 427: snprintf(buf, sizeof(buf), "array.data.%u", i);
! 428: if (structs_struct2xmlrpc(etype,
! 429: (char *)ary->elems + (i * etype->size), NULL,
! 430: xtype, xdata, buf) == -1)
! 431: return (-1);
! 432: }
! 433: break;
! 434: }
! 435: case STRUCTS_TYPE_FIXEDARRAY:
! 436: {
! 437: const struct structs_type *const etype = type->args[0].v;
! 438: const u_int length = type->args[2].i;
! 439: u_int i;
! 440:
! 441: /* Reset destination value to be an empty array */
! 442: if (structs_array_reset(xtype, "array.data", xdata) == -1)
! 443: return (-1);
! 444:
! 445: /* Copy over each element in the array */
! 446: for (i = 0; i < length; i++) {
! 447: char buf[32];
! 448:
! 449: /* Add a new element to the dest array */
! 450: if (structs_array_insert(xtype,
! 451: "array.data", i, xdata) == -1)
! 452: return (-1);
! 453:
! 454: /* Set its value */
! 455: snprintf(buf, sizeof(buf), "array.data.%u", i);
! 456: if (structs_struct2xmlrpc(etype,
! 457: (char *)data + (i * etype->size), NULL,
! 458: xtype, xdata, buf) == -1)
! 459: return (-1);
! 460: }
! 461: break;
! 462: }
! 463: case STRUCTS_TYPE_STRUCTURE:
! 464: {
! 465: const struct structs_field *field = type->args[0].v;
! 466: u_int i;
! 467:
! 468: /* Reset destination value to be an empty struct,
! 469: which really means just an empty array of members. */
! 470: if (structs_array_reset(xtype, "struct", xdata) == -1)
! 471: return (-1);
! 472:
! 473: /* Copy over each field in the structure to the member array */
! 474: for (i = 0; field->name != NULL; i++, field++) {
! 475: char buf[32];
! 476:
! 477: /* Add a new element to the member array */
! 478: if (structs_array_insert(xtype,
! 479: "struct", i, xdata) == -1)
! 480: return (-1);
! 481:
! 482: /* Set the new member's name */
! 483: snprintf(buf, sizeof(buf), "struct.%u.name", i);
! 484: if (structs_set_string(xtype,
! 485: buf, field->name, xdata, NULL, 0) == -1)
! 486: return (-1);
! 487:
! 488: /* Set the new member's value */
! 489: snprintf(buf, sizeof(buf), "struct.%u.value", i);
! 490: if (structs_struct2xmlrpc(field->type,
! 491: (char *)data + field->offset, NULL,
! 492: xtype, xdata, buf) == -1)
! 493: return (-1);
! 494: }
! 495: break;
! 496: }
! 497: case STRUCTS_TYPE_UNION:
! 498: {
! 499: const struct structs_ufield *const fields = type->args[0].v;
! 500: const struct structs_union *const un = data;
! 501: const struct structs_ufield *field;
! 502:
! 503: /* Reset destination value to be an empty struct,
! 504: which really means just an empty array of members. */
! 505: if (structs_array_reset(xtype, "struct", xdata) == -1)
! 506: return (-1);
! 507:
! 508: /* Find field */
! 509: for (field = fields; field->name != NULL
! 510: && strcmp(un->field_name, field->name) != 0; field++);
! 511: if (field->name == NULL) {
! 512: assert(0);
! 513: errno = EINVAL;
! 514: return (-1);
! 515: }
! 516:
! 517: /* Add a new element to the member array */
! 518: if (structs_array_insert(xtype, "struct", 0, xdata) == -1)
! 519: return (-1);
! 520:
! 521: /* Set the new member's name */
! 522: if (structs_set_string(xtype, "struct.0.name",
! 523: field->name, xdata, NULL, 0) == -1)
! 524: return (-1);
! 525:
! 526: /* Set the new member's value */
! 527: if (structs_struct2xmlrpc(field->type,
! 528: un->un, NULL, xtype, xdata, "struct.0.value") == -1)
! 529: return (-1);
! 530: break;
! 531: }
! 532: default:
! 533: assert(0);
! 534: return (-1);
! 535: }
! 536: return (0);
! 537: }
! 538:
! 539: /*
! 540: * Copy the contents of an XML-RPC "value" structure into a normal structure.
! 541: */
! 542: int
! 543: structs_xmlrpc2struct(const struct structs_type *xtype, const void *xdata,
! 544: const char *xname, const struct structs_type *type,
! 545: void *data, const char *sname, char *ebuf, size_t emax)
! 546: {
! 547: const struct structs_union *xun;
! 548:
! 549: /* Safety */
! 550: snprintf(ebuf, emax, "Unknown error");
! 551:
! 552: /* Find source and dest data */
! 553: if ((xtype = structs_find(xtype, xname, (void **)&xdata, 0)) == NULL)
! 554: goto fail_errno;
! 555: if ((type = structs_find(type, sname, &data, 1)) == NULL)
! 556: goto fail_errno;
! 557:
! 558: /* Source type must always be an XML-RPC value */
! 559: if (xtype != &structs_type_xmlrpc_value) {
! 560: snprintf(ebuf, emax, "xtype != &structs_type_xmlrpc_value");
! 561: errno = EINVAL;
! 562: return (-1);
! 563: }
! 564: assert (xtype->tclass == STRUCTS_TYPE_UNION);
! 565:
! 566: /* Dereference through pointer(s) */
! 567: while (type->tclass == STRUCTS_TYPE_POINTER) {
! 568: type = type->args[0].v;
! 569: data = *((void **)data);
! 570: }
! 571:
! 572: /* Get union info */
! 573: xun = xdata;
! 574:
! 575: /* Check which union field is in use and transfer accordingly */
! 576: if (strcmp(xun->field_name, "i4") == 0
! 577: || strcmp(xun->field_name, "int") == 0
! 578: || strcmp(xun->field_name, "boolean") == 0
! 579: || strcmp(xun->field_name, "double") == 0
! 580: || strcmp(xun->field_name, "string") == 0
! 581: || strcmp(xun->field_name, "dateTime.iso8601") == 0
! 582: || strcmp(xun->field_name, "base64") == 0) {
! 583: const char *xfname = xun->field_name;
! 584: char *s;
! 585:
! 586: if ((s = structs_get_string(xtype,
! 587: xfname, xdata, TYPED_MEM_TEMP)) == NULL)
! 588: goto fail_errno;
! 589: if (structs_set_string(type, NULL, s, data, ebuf, emax) == -1) {
! 590: FREE(TYPED_MEM_TEMP, s);
! 591: return (-1);
! 592: }
! 593: FREE(TYPED_MEM_TEMP, s);
! 594: } else if (strcmp(xun->field_name, "struct") == 0) {
! 595: int is_struct;
! 596: u_int len;
! 597: u_int i;
! 598:
! 599: /* Check destination type */
! 600: if (type->tclass != STRUCTS_TYPE_STRUCTURE
! 601: && type->tclass != STRUCTS_TYPE_UNION) {
! 602: snprintf(ebuf, emax, "can't convert XML-RPC struct");
! 603: errno = EINVAL;
! 604: return (-1);
! 605: }
! 606: is_struct = (type->tclass == STRUCTS_TYPE_STRUCTURE);
! 607:
! 608: /* Copy structure members */
! 609: if ((len = structs_array_length(xtype, "struct", xdata)) == -1)
! 610: goto fail_errno;
! 611: for (i = 0; i < len; i++) {
! 612: const struct structs_type *ftype = type;
! 613: void *fdata = data;
! 614: char buf[32];
! 615: char *mname;
! 616:
! 617: /* Get member field name */
! 618: snprintf(buf, sizeof(buf), "struct.%u.name", i);
! 619: if ((mname = structs_get_string(xtype,
! 620: buf, xdata, TYPED_MEM_TEMP)) == NULL)
! 621: goto fail_errno;
! 622:
! 623: /* Find field in struct or union */
! 624: if ((ftype = structs_find(type,
! 625: mname, &fdata, 1)) == NULL) {
! 626: if (errno != ENOENT) {
! 627: FREE(TYPED_MEM_TEMP, mname);
! 628: goto fail_errno;
! 629: }
! 630: snprintf(ebuf, emax, "unknown %s field \"%s\"",
! 631: is_struct ? "struct" : "union", mname);
! 632: FREE(TYPED_MEM_TEMP, mname);
! 633: errno = ENOENT;
! 634: return (-1);
! 635: }
! 636: FREE(TYPED_MEM_TEMP, mname);
! 637:
! 638: /* Copy over value */
! 639: snprintf(buf, sizeof(buf), "struct.%u.value", i);
! 640: if (structs_xmlrpc2struct(xtype, xdata, buf,
! 641: ftype, fdata, NULL, ebuf, emax) == -1)
! 642: return (-1);
! 643: }
! 644: } else if (strcmp(xun->field_name, "array") == 0) {
! 645: const struct structs_type *const etype = type->args[0].v;
! 646: struct structs_array *const ary = data;
! 647: const u_int length = type->args[2].i; /* if fixedarray */
! 648: const struct structs_type *xatype;
! 649: const struct structs_array *xary;
! 650: int fixed;
! 651: u_int i;
! 652:
! 653: /* Check destination type */
! 654: if (type->tclass != STRUCTS_TYPE_ARRAY
! 655: && type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
! 656: snprintf(ebuf, emax, "can't convert XML-RPC array");
! 657: errno = EINVAL;
! 658: return (-1);
! 659: }
! 660: fixed = (type->tclass == STRUCTS_TYPE_FIXEDARRAY);
! 661:
! 662: /* Dig for the actual source array */
! 663: xary = xdata;
! 664: if ((xatype = structs_find(xtype,
! 665: "array.data", (void **)&xary, 0)) == NULL)
! 666: goto fail_errno;
! 667:
! 668: /* Reset destination array */
! 669: if (structs_reset(type, NULL, data) == -1)
! 670: goto fail_errno;
! 671:
! 672: /* Check length for fixed arrays */
! 673: if (fixed && xary->length > length) {
! 674: snprintf(ebuf, emax, "XML-RPC array is too long");
! 675: errno = EDOM;
! 676: return (-1);
! 677: }
! 678:
! 679: /* Copy over each element in the array */
! 680: for (i = 0; i < xary->length; i++) {
! 681: char buf[32];
! 682: void *elem;
! 683:
! 684: /* Add/set new element in the dest array */
! 685: if (fixed)
! 686: elem = (char *)data + (i * etype->size);
! 687: else {
! 688: if (structs_array_insert(type,
! 689: NULL, i, data) == -1)
! 690: goto fail_errno;
! 691: elem = (char *)ary->elems + (i * etype->size);
! 692: }
! 693:
! 694: /* Set its value */
! 695: snprintf(buf, sizeof(buf), "%u", i);
! 696: if (structs_xmlrpc2struct(xatype, xary, buf, etype,
! 697: elem, NULL, ebuf, emax) == -1)
! 698: return (-1);
! 699: }
! 700: } else {
! 701: snprintf(ebuf, emax, "unsupported XML-RPC type \"%s\"",
! 702: xun->field_name);
! 703: errno = EINVAL;
! 704: return (-1);
! 705: }
! 706:
! 707: /* Done */
! 708: return (0);
! 709:
! 710: fail_errno:
! 711: /* Return with error */
! 712: snprintf(ebuf, emax, "%s", strerror(errno));
! 713: return (-1);
! 714: }
! 715:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>