Annotation of embedaddon/libpdel/structs/structs_xmlrpc.c, revision 1.1.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>