File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / structs / structs_xmlrpc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:25:53 2012 UTC (13 years, 1 month ago) by misho
Branches: libpdel, MAIN
CVS tags: v0_5_3, HEAD
libpdel

    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, &param_fields);
  150: 
  151: /************************************************************************
  152: 				params
  153: ************************************************************************/
  154: 
  155: static const struct structs_type params_type
  156: 	= STRUCTS_ARRAY_TYPE(&param_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, &params_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, &params_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>