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, &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>