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, ¶m_fields);
150:
151: /************************************************************************
152: params
153: ************************************************************************/
154:
155: static const struct structs_type params_type
156: = STRUCTS_ARRAY_TYPE(¶m_type, "xmlrpc_params", "param");
157:
158: /************************************************************************
159: fault
160: ************************************************************************/
161:
162: static const struct structs_field fault_fields[] = {
163: STRUCTS_STRUCT_FIELD(xmlrpc_fault, value, &structs_type_xmlrpc_value),
164: STRUCTS_STRUCT_FIELD_END
165: };
166: const struct structs_type structs_type_xmlrpc_fault
167: = STRUCTS_STRUCT_TYPE(xmlrpc_fault, &fault_fields);
168:
169: /************************************************************************
170: request
171: ************************************************************************/
172:
173: static const struct structs_field request_fields[] = {
174: STRUCTS_STRUCT_FIELD(xmlrpc_request, methodName, &string_type),
175: STRUCTS_STRUCT_FIELD(xmlrpc_request, params, ¶ms_type),
176: STRUCTS_STRUCT_FIELD_END
177: };
178: const struct structs_type structs_type_xmlrpc_request
179: = STRUCTS_STRUCT_TYPE(xmlrpc_request, &request_fields);
180:
181: /************************************************************************
182: response
183: ************************************************************************/
184:
185: static const struct structs_ufield response_fields[] = {
186: STRUCTS_UNION_FIELD(params, ¶ms_type),
187: STRUCTS_UNION_FIELD(fault, &structs_type_xmlrpc_fault),
188: STRUCTS_UNION_FIELD_END
189: };
190: const struct structs_type structs_type_xmlrpc_response
191: = STRUCTS_UNION_TYPE(xmlrpc_response, &response_fields);
192:
193: /************************************************************************
194: fault (compact form)
195: ************************************************************************/
196:
197: static const struct structs_type fault_string_type
198: = STRUCTS_STRING_TYPE("xmlrpc_fault_string", 0);
199:
200: static const struct structs_field compact_fault_fields[] = {
201: STRUCTS_STRUCT_FIELD(xmlrpc_compact_fault,
202: faultCode, &structs_type_int32),
203: STRUCTS_STRUCT_FIELD(xmlrpc_compact_fault,
204: faultString, &fault_string_type),
205: STRUCTS_STRUCT_FIELD_END
206: };
207: const struct structs_type structs_type_xmlrpc_compact_fault
208: = STRUCTS_STRUCT_TYPE(xmlrpc_compact_fault, &compact_fault_fields);
209:
210: /************************************************************************
211: FUNCTIONS
212: ************************************************************************/
213:
214: /*
215: * Create an XML-RPC request structure with the given parameters.
216: */
217: struct xmlrpc_request *
218: structs_xmlrpc_build_request(const char *mtype, const char *methodName,
219: u_int nparams, const struct structs_type **types, const void **datas)
220: {
221: const struct structs_type *const xtype = &structs_type_xmlrpc_request;
222: struct xmlrpc_request *xreq;
223: u_int i;
224:
225: /* Create new XML-RPC request structure */
226: if ((xreq = MALLOC(mtype, sizeof(*xreq))) == NULL)
227: return (NULL);
228: if (structs_init(xtype, NULL, xreq) == -1) {
229: FREE(mtype, xreq);
230: return (NULL);
231: }
232:
233: /* Set method name */
234: if (structs_set_string(xtype,
235: "methodName", methodName, xreq, NULL, 0) == -1)
236: goto fail;
237:
238: /* Copy parameters into request */
239: for (i = 0; i < nparams; i++) {
240: const void *const data = datas[i];
241: char xname[32];
242:
243: /* Add another element to params array */
244: if (structs_array_insert(xtype, "params", i, xreq) == -1)
245: goto fail;
246: snprintf(xname, sizeof(xname), "params.%u.value", i);
247:
248: /* Explode parameter unless already exploded */
249: if (types != NULL) {
250: if (structs_struct2xmlrpc(types[i], data, NULL,
251: xtype, xreq, xname) == -1)
252: goto fail;
253: } else {
254: if (structs_set(&structs_type_xmlrpc_value,
255: data, xname, xreq) == -1)
256: goto fail;
257: }
258: }
259:
260: /* Done */
261: return (xreq);
262:
263: fail:
264: structs_free(xtype, NULL, xreq);
265: FREE(mtype, xreq);
266: return (NULL);
267: }
268:
269: /*
270: * Create an XML-RPC response structure with the given return value.
271: */
272: struct xmlrpc_response_union *
273: structs_xmlrpc_build_response(const char *mtype,
274: const struct structs_type *type, const void *data)
275: {
276: const struct structs_type *const xtype = &structs_type_xmlrpc_response;
277: struct xmlrpc_response_union *xrep;
278:
279: /* Create new XML-RPC response structure */
280: if ((xrep = MALLOC(mtype, sizeof(*xrep))) == NULL)
281: return (NULL);
282: if (structs_init(xtype, NULL, xrep) == -1) {
283: FREE(mtype, xrep);
284: return (NULL);
285: }
286:
287: /* Add a single parameter */
288: if (structs_array_insert(xtype, "params", 0, xrep) == -1)
289: goto fail;
290:
291: /* Copy parameter, optionally compacting it */
292: if (type != NULL) {
293: if (structs_struct2xmlrpc(type, data,
294: NULL, xtype, xrep, "params.0.value") == -1)
295: goto fail;
296: } else {
297: if (structs_set(&structs_type_xmlrpc_value,
298: data, "params.0.value", xrep) == -1)
299: goto fail;
300: }
301:
302: /* Done */
303: return (xrep);
304:
305: fail:
306: structs_free(xtype, NULL, xrep);
307: FREE(mtype, xrep);
308: return (NULL);
309: }
310:
311: /*
312: * Create an XML-RPC fault response structure with the given fault.
313: */
314: struct xmlrpc_response_union *
315: structs_xmlrpc_build_fault_response(const char *mtype,
316: const struct xmlrpc_compact_fault *fault)
317: {
318: const struct structs_type *const xtype = &structs_type_xmlrpc_response;
319: struct xmlrpc_response_union *xrep;
320:
321: /* Create new XML-RPC response structure */
322: if ((xrep = MALLOC(mtype, sizeof(*xrep))) == NULL)
323: return (NULL);
324: if (structs_init(xtype, NULL, xrep) == -1) {
325: FREE(mtype, xrep);
326: return (NULL);
327: }
328:
329: /* Set fault */
330: if (structs_struct2xmlrpc(&structs_type_xmlrpc_compact_fault,
331: fault, NULL, xtype, xrep, "fault.value") == -1)
332: goto fail;
333:
334: /* Done */
335: return (xrep);
336:
337: fail:
338: structs_free(xtype, NULL, xrep);
339: FREE(mtype, xrep);
340: return (NULL);
341: }
342:
343: /*
344: * Copy the contents of a normal structure into an XML-RPC "value" structure.
345: */
346: int
347: structs_struct2xmlrpc(const struct structs_type *type,
348: const void *data, const char *sname,
349: const struct structs_type *xtype, void *xdata, const char *xname)
350: {
351:
352: /* Find source and dest data */
353: if ((type = structs_find(type, sname, (void **)&data, 0)) == NULL)
354: return (-1);
355: if ((xtype = structs_find(xtype, xname, &xdata, 1)) == NULL)
356: return (-1);
357:
358: /* Destination type must always be an XML-RPC value */
359: if (xtype != &structs_type_xmlrpc_value) {
360: errno = EINVAL;
361: return (-1);
362: }
363:
364: /* Dereference through pointer(s) */
365: while (type->tclass == STRUCTS_TYPE_POINTER) {
366: type = type->args[0].v;
367: data = *((void **)data);
368: }
369:
370: switch (type->tclass) {
371: case STRUCTS_TYPE_PRIMITIVE:
372: {
373: const char *xprim;
374: char *s;
375:
376: /* Get corresponding XML-RPC primitive type */
377: if (type == &structs_type_int32
378: || (sizeof(int) == 4 && type == &structs_type_int))
379: xprim = "i4";
380: else if (strcmp(type->name, "float") == 0
381: || strcmp(type->name, "double") == 0)
382: xprim = "double";
383: else if (strcmp(type->name, "boolean") == 0)
384: xprim = "boolean";
385: else if (type == &structs_type_time_iso8601)
386: xprim = "dateTime.iso8601";
387: else if (strcmp(type->name, "data") == 0
388: && type->args[0].v == NULL) /* XXX same charmap */
389: xprim = "base64";
390: else
391: xprim = "string";
392:
393: /* Get primitive value as a string */
394: if ((s = structs_get_string(type,
395: NULL, data, TYPED_MEM_TEMP)) == NULL)
396: return (-1);
397:
398: /* Set primitive value as a string */
399: if (structs_set_string(xtype,
400: xprim, s, xdata, NULL, 0) == -1) {
401: FREE(TYPED_MEM_TEMP, s);
402: return (-1);
403: }
404: FREE(TYPED_MEM_TEMP, s);
405: break;
406: }
407: case STRUCTS_TYPE_ARRAY:
408: {
409: const struct structs_type *const etype = type->args[0].v;
410: const struct structs_array *const ary = data;
411: u_int i;
412:
413: /* Reset destination value to be an empty array */
414: if (structs_array_reset(xtype, "array.data", xdata) == -1)
415: return (-1);
416:
417: /* Copy over each element in the array */
418: for (i = 0; i < ary->length; i++) {
419: char buf[32];
420:
421: /* Add a new element to the dest array */
422: if (structs_array_insert(xtype,
423: "array.data", i, xdata) == -1)
424: return (-1);
425:
426: /* Set its value */
427: snprintf(buf, sizeof(buf), "array.data.%u", i);
428: if (structs_struct2xmlrpc(etype,
429: (char *)ary->elems + (i * etype->size), NULL,
430: xtype, xdata, buf) == -1)
431: return (-1);
432: }
433: break;
434: }
435: case STRUCTS_TYPE_FIXEDARRAY:
436: {
437: const struct structs_type *const etype = type->args[0].v;
438: const u_int length = type->args[2].i;
439: u_int i;
440:
441: /* Reset destination value to be an empty array */
442: if (structs_array_reset(xtype, "array.data", xdata) == -1)
443: return (-1);
444:
445: /* Copy over each element in the array */
446: for (i = 0; i < length; i++) {
447: char buf[32];
448:
449: /* Add a new element to the dest array */
450: if (structs_array_insert(xtype,
451: "array.data", i, xdata) == -1)
452: return (-1);
453:
454: /* Set its value */
455: snprintf(buf, sizeof(buf), "array.data.%u", i);
456: if (structs_struct2xmlrpc(etype,
457: (char *)data + (i * etype->size), NULL,
458: xtype, xdata, buf) == -1)
459: return (-1);
460: }
461: break;
462: }
463: case STRUCTS_TYPE_STRUCTURE:
464: {
465: const struct structs_field *field = type->args[0].v;
466: u_int i;
467:
468: /* Reset destination value to be an empty struct,
469: which really means just an empty array of members. */
470: if (structs_array_reset(xtype, "struct", xdata) == -1)
471: return (-1);
472:
473: /* Copy over each field in the structure to the member array */
474: for (i = 0; field->name != NULL; i++, field++) {
475: char buf[32];
476:
477: /* Add a new element to the member array */
478: if (structs_array_insert(xtype,
479: "struct", i, xdata) == -1)
480: return (-1);
481:
482: /* Set the new member's name */
483: snprintf(buf, sizeof(buf), "struct.%u.name", i);
484: if (structs_set_string(xtype,
485: buf, field->name, xdata, NULL, 0) == -1)
486: return (-1);
487:
488: /* Set the new member's value */
489: snprintf(buf, sizeof(buf), "struct.%u.value", i);
490: if (structs_struct2xmlrpc(field->type,
491: (char *)data + field->offset, NULL,
492: xtype, xdata, buf) == -1)
493: return (-1);
494: }
495: break;
496: }
497: case STRUCTS_TYPE_UNION:
498: {
499: const struct structs_ufield *const fields = type->args[0].v;
500: const struct structs_union *const un = data;
501: const struct structs_ufield *field;
502:
503: /* Reset destination value to be an empty struct,
504: which really means just an empty array of members. */
505: if (structs_array_reset(xtype, "struct", xdata) == -1)
506: return (-1);
507:
508: /* Find field */
509: for (field = fields; field->name != NULL
510: && strcmp(un->field_name, field->name) != 0; field++);
511: if (field->name == NULL) {
512: assert(0);
513: errno = EINVAL;
514: return (-1);
515: }
516:
517: /* Add a new element to the member array */
518: if (structs_array_insert(xtype, "struct", 0, xdata) == -1)
519: return (-1);
520:
521: /* Set the new member's name */
522: if (structs_set_string(xtype, "struct.0.name",
523: field->name, xdata, NULL, 0) == -1)
524: return (-1);
525:
526: /* Set the new member's value */
527: if (structs_struct2xmlrpc(field->type,
528: un->un, NULL, xtype, xdata, "struct.0.value") == -1)
529: return (-1);
530: break;
531: }
532: default:
533: assert(0);
534: return (-1);
535: }
536: return (0);
537: }
538:
539: /*
540: * Copy the contents of an XML-RPC "value" structure into a normal structure.
541: */
542: int
543: structs_xmlrpc2struct(const struct structs_type *xtype, const void *xdata,
544: const char *xname, const struct structs_type *type,
545: void *data, const char *sname, char *ebuf, size_t emax)
546: {
547: const struct structs_union *xun;
548:
549: /* Safety */
550: snprintf(ebuf, emax, "Unknown error");
551:
552: /* Find source and dest data */
553: if ((xtype = structs_find(xtype, xname, (void **)&xdata, 0)) == NULL)
554: goto fail_errno;
555: if ((type = structs_find(type, sname, &data, 1)) == NULL)
556: goto fail_errno;
557:
558: /* Source type must always be an XML-RPC value */
559: if (xtype != &structs_type_xmlrpc_value) {
560: snprintf(ebuf, emax, "xtype != &structs_type_xmlrpc_value");
561: errno = EINVAL;
562: return (-1);
563: }
564: assert (xtype->tclass == STRUCTS_TYPE_UNION);
565:
566: /* Dereference through pointer(s) */
567: while (type->tclass == STRUCTS_TYPE_POINTER) {
568: type = type->args[0].v;
569: data = *((void **)data);
570: }
571:
572: /* Get union info */
573: xun = xdata;
574:
575: /* Check which union field is in use and transfer accordingly */
576: if (strcmp(xun->field_name, "i4") == 0
577: || strcmp(xun->field_name, "int") == 0
578: || strcmp(xun->field_name, "boolean") == 0
579: || strcmp(xun->field_name, "double") == 0
580: || strcmp(xun->field_name, "string") == 0
581: || strcmp(xun->field_name, "dateTime.iso8601") == 0
582: || strcmp(xun->field_name, "base64") == 0) {
583: const char *xfname = xun->field_name;
584: char *s;
585:
586: if ((s = structs_get_string(xtype,
587: xfname, xdata, TYPED_MEM_TEMP)) == NULL)
588: goto fail_errno;
589: if (structs_set_string(type, NULL, s, data, ebuf, emax) == -1) {
590: FREE(TYPED_MEM_TEMP, s);
591: return (-1);
592: }
593: FREE(TYPED_MEM_TEMP, s);
594: } else if (strcmp(xun->field_name, "struct") == 0) {
595: int is_struct;
596: u_int len;
597: u_int i;
598:
599: /* Check destination type */
600: if (type->tclass != STRUCTS_TYPE_STRUCTURE
601: && type->tclass != STRUCTS_TYPE_UNION) {
602: snprintf(ebuf, emax, "can't convert XML-RPC struct");
603: errno = EINVAL;
604: return (-1);
605: }
606: is_struct = (type->tclass == STRUCTS_TYPE_STRUCTURE);
607:
608: /* Copy structure members */
609: if ((len = structs_array_length(xtype, "struct", xdata)) == -1)
610: goto fail_errno;
611: for (i = 0; i < len; i++) {
612: const struct structs_type *ftype = type;
613: void *fdata = data;
614: char buf[32];
615: char *mname;
616:
617: /* Get member field name */
618: snprintf(buf, sizeof(buf), "struct.%u.name", i);
619: if ((mname = structs_get_string(xtype,
620: buf, xdata, TYPED_MEM_TEMP)) == NULL)
621: goto fail_errno;
622:
623: /* Find field in struct or union */
624: if ((ftype = structs_find(type,
625: mname, &fdata, 1)) == NULL) {
626: if (errno != ENOENT) {
627: FREE(TYPED_MEM_TEMP, mname);
628: goto fail_errno;
629: }
630: snprintf(ebuf, emax, "unknown %s field \"%s\"",
631: is_struct ? "struct" : "union", mname);
632: FREE(TYPED_MEM_TEMP, mname);
633: errno = ENOENT;
634: return (-1);
635: }
636: FREE(TYPED_MEM_TEMP, mname);
637:
638: /* Copy over value */
639: snprintf(buf, sizeof(buf), "struct.%u.value", i);
640: if (structs_xmlrpc2struct(xtype, xdata, buf,
641: ftype, fdata, NULL, ebuf, emax) == -1)
642: return (-1);
643: }
644: } else if (strcmp(xun->field_name, "array") == 0) {
645: const struct structs_type *const etype = type->args[0].v;
646: struct structs_array *const ary = data;
647: const u_int length = type->args[2].i; /* if fixedarray */
648: const struct structs_type *xatype;
649: const struct structs_array *xary;
650: int fixed;
651: u_int i;
652:
653: /* Check destination type */
654: if (type->tclass != STRUCTS_TYPE_ARRAY
655: && type->tclass != STRUCTS_TYPE_FIXEDARRAY) {
656: snprintf(ebuf, emax, "can't convert XML-RPC array");
657: errno = EINVAL;
658: return (-1);
659: }
660: fixed = (type->tclass == STRUCTS_TYPE_FIXEDARRAY);
661:
662: /* Dig for the actual source array */
663: xary = xdata;
664: if ((xatype = structs_find(xtype,
665: "array.data", (void **)&xary, 0)) == NULL)
666: goto fail_errno;
667:
668: /* Reset destination array */
669: if (structs_reset(type, NULL, data) == -1)
670: goto fail_errno;
671:
672: /* Check length for fixed arrays */
673: if (fixed && xary->length > length) {
674: snprintf(ebuf, emax, "XML-RPC array is too long");
675: errno = EDOM;
676: return (-1);
677: }
678:
679: /* Copy over each element in the array */
680: for (i = 0; i < xary->length; i++) {
681: char buf[32];
682: void *elem;
683:
684: /* Add/set new element in the dest array */
685: if (fixed)
686: elem = (char *)data + (i * etype->size);
687: else {
688: if (structs_array_insert(type,
689: NULL, i, data) == -1)
690: goto fail_errno;
691: elem = (char *)ary->elems + (i * etype->size);
692: }
693:
694: /* Set its value */
695: snprintf(buf, sizeof(buf), "%u", i);
696: if (structs_xmlrpc2struct(xatype, xary, buf, etype,
697: elem, NULL, ebuf, emax) == -1)
698: return (-1);
699: }
700: } else {
701: snprintf(ebuf, emax, "unsupported XML-RPC type \"%s\"",
702: xun->field_name);
703: errno = EINVAL;
704: return (-1);
705: }
706:
707: /* Done */
708: return (0);
709:
710: fail_errno:
711: /* Return with error */
712: snprintf(ebuf, emax, "%s", strerror(errno));
713: return (-1);
714: }
715:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>