/******************************************************************************* * Copyright (C) 2004-2006 Intel Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of Intel Corp. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /** * @author Eugene Yarmosh * @author Vadim Revyakin */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #if defined (__SVR4) && defined (__sun) #include #endif #include #include #include "wsman-xml-api.h" #include "wsman-soap.h" #include "wsman-xml.h" #include "wsman-dispatcher.h" #include "wsman-xml-serializer.h" #include "wsman-xml-serialize.h" #include "wsman-soap-envelope.h" struct __WsSerializerMemEntry { char buf[0]; }; typedef struct __WsSerializerMemEntry WsSerializerMemEntry; struct __WsSerializerContext { pthread_mutex_t lock; list_t *WsSerializerAllocList; }; WsSerializerContextH ws_serializer_init() { WsSerializerContextH serializercntx = NULL; serializercntx = u_malloc(sizeof(struct __WsSerializerContext)); if(serializercntx == NULL) return NULL; serializercntx->WsSerializerAllocList = list_create(LISTCOUNT_T_MAX); if(serializercntx->WsSerializerAllocList == NULL) { u_free(serializercntx); return NULL; } u_init_lock(serializercntx); return serializercntx; } int ws_serializer_cleanup(WsSerializerContextH serctx) { if(serctx && serctx->WsSerializerAllocList) { ws_serializer_free_all(serctx); u_destroy_lock(serctx); list_destroy(serctx->WsSerializerAllocList); u_free(serctx); } return 0; } void *xml_serializer_alloc(XmlSerializationData * data, int size, int zeroInit) { void *ptr = ws_serializer_alloc(data->serctx, size); TRACE_ENTER; if (ptr && zeroInit) memset(ptr, 0, size); TRACE_EXIT; return ptr; } int xml_serializer_free(XmlSerializationData * data, void *buf) { return ws_serializer_free(data->serctx, buf); } WsXmlNodeH xml_serializer_add_child(XmlSerializationData * data, char *value) { const char *name = data->elementInfo->name; const char *ns = data->elementInfo->ns; WsXmlNodeH node; TRACE_ENTER; debug("name = %s; value(%p) = %s", name ? name : "NULL", value, value ? value : "NULL"); node = ws_xml_add_child(data->xmlNode, ns, name, value); TRACE_EXIT; return node; } WsXmlNodeH xml_serializer_get_child(XmlSerializationData * data) { WsXmlNodeH node; const char *name = data->elementInfo->name; const char *ns = data->elementInfo->ns; TRACE_ENTER; debug("name = %s:%s in %s [%d]", ns, name, ws_xml_get_node_local_name(data->xmlNode), data->index); node = ws_xml_get_child(data->xmlNode, data->index, ns, name); #if 0 if (g_NameNameAliaseTable) { int index = 0; while (node == NULL && g_NameNameAliaseTable[index].name != NULL) { if (!strcmp(g_NameNameAliaseTable[index].name, name)) node = ws_xml_get_child(data->xmlNode, data->index, ns, g_NameNameAliaseTable [index].aliase); index++; } } #endif debug("returned %p; %s", node, node ? ws_xml_get_node_local_name(node) : ""); TRACE_EXIT; return node; } static int get_struct_align(void) { typedef struct { XML_TYPE_UINT8 a; struct { char x; void *y; } b; } dummy; return (char *) &(((dummy *) NULL)->b) - (char *) NULL; } static int handle_attrs(struct __XmlSerializationData *data, WsXmlNodeH node, size_t sz) { typedef struct { XML_TYPE_UINT8 a; XML_NODE_ATTR *b; } dummy; int ret = 0; char *savedBufPtr = DATA_BUF(data); size_t al; size_t pad; int i; XML_NODE_ATTR **attrsp; XML_NODE_ATTR *attr; WsXmlAttrH xmlattr; char *src, *dstPtr; int dstSize; TRACE_ENTER; debug("node name = %s", ws_xml_get_node_local_name(node)); if (!XML_IS_ATTRS(data->elementInfo)) { debug("No attrs"); goto DONE; } DATA_BUF(data) = DATA_BUF(data) + sz; al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } debug("initial DATABUF = %p", DATA_BUF(data)); DATA_BUF(data) = DATA_BUF(data) + pad; debug("alligned databuf = %p; pad = 0x%x", DATA_BUF(data), pad); if (data->mode == XML_SMODE_FREE_MEM) { // XXXXX free memory goto DONE; } if (data->mode == XML_SMODE_SERIALIZE) { XML_NODE_ATTR *attrs = *((XML_NODE_ATTR **) DATA_BUF(data)); debug("attrs = %p", attrs); while (attrs) { debug("add attr. %s:%s = %s", attrs->ns, attrs->name, attrs->value); if (ws_xml_add_node_attr(node, attrs->ns, attrs->name, attrs->value) == NULL) { error("could not add attr. %s:%s = %s", attrs->ns, attrs->name, attrs->value); ret = 1; goto DONE; } attrs = attrs->next; } goto DONE; } // XML_SMODE_DESERIALIZE attrsp = (XML_NODE_ATTR **) DATA_BUF(data); *attrsp = NULL; for (i = 0; i < ws_xml_get_node_attr_count(node); i++) { attr = xml_serializer_alloc(data, sizeof(XML_NODE_ATTR), 1); if (attr == NULL) { error("no memory"); ret = 1; goto DONE; } xmlattr = ws_xml_get_node_attr(node, i); if (xmlattr == NULL) { error("could not get attr %d", i); ret = 1; goto DONE; } src = ws_xml_get_attr_ns(xmlattr); if (!(src == NULL || *src == 0)) { dstSize = 1 + (int )strlen(src); dstPtr = (char *) xml_serializer_alloc(data, dstSize, 1); if (dstPtr == NULL) { error("no memory"); ret = 1; goto DONE; } strncpy(dstPtr, src, dstSize); attr->ns = dstPtr; } src = ws_xml_get_attr_name(xmlattr); if (!(src == NULL || *src == 0)) { dstSize = 1 + (int )strlen(src); dstPtr = (char *) xml_serializer_alloc(data, dstSize, 1); if (dstPtr == NULL) { error("no memory"); ret = 1; goto DONE; } strncpy(dstPtr, src, dstSize); attr->name = dstPtr; } src = ws_xml_get_attr_value(xmlattr); if (!(src == NULL || *src == 0)) { dstSize = 1 + (int )strlen(src); dstPtr = (char *) xml_serializer_alloc(data, dstSize, 1); if (dstPtr == NULL) { error("no memory"); ret = 1; goto DONE; } strncpy(dstPtr, src, dstSize); attr->value = dstPtr; } attr->next = *attrsp; *attrsp = attr; } DONE: DATA_BUF(data) = savedBufPtr; TRACE_EXIT; return ret; } static int do_serialize_int(XmlSerializationData * data, int valSize) { WsXmlNodeH child = NULL; XML_TYPE_INT64 tmp; int retVal = DATA_ALL_SIZE(data); char *end; char *str; TRACE_ENTER; debug("handle %d INT%d %s;", DATA_COUNT(data), 8 * valSize, data->elementInfo->name); if (DATA_BUF(data) + retVal > data->stopper) { error("size of %d structures %s exceeds stopper (%p > %p)", DATA_COUNT(data), DATA_ELNAME(data), DATA_BUF(data) + retVal, data->stopper); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) { DATA_BUF(data) = DATA_BUF(data) + retVal; goto DONE; } if ((data->mode != XML_SMODE_DESERIALIZE && data->mode != XML_SMODE_SERIALIZE)) { error("invalid mode %d", data->mode); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } for (data->index = 0; data->index < DATA_COUNT(data); data->index++) { debug("%s[%d] = %p", data->elementInfo->name, data->index, data->elementBuf); if (data->mode == XML_SMODE_SERIALIZE) { debug("value size: %d", valSize); if (valSize == 1) tmp = *((XML_TYPE_INT8 *) data->elementBuf); else if (valSize == 2) tmp = *((XML_TYPE_INT16 *) data-> elementBuf); else if (valSize == 4) tmp = *((XML_TYPE_INT32 *) data-> elementBuf); else if (valSize == 8) tmp = *((XML_TYPE_INT64 *) data-> elementBuf); else { error("unsupported uint size + %d", 8 * valSize); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (((child = xml_serializer_add_child(data, NULL)) == NULL) || (ws_xml_set_node_long(child, tmp)) != 0) { debug("could not add child %s[%d]", DATA_ELNAME(data), data->index); retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } } if (data->mode == XML_SMODE_DESERIALIZE) { if ((child = xml_serializer_get_child(data)) == NULL) { error ("not enough (%d < %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } if ((str = ws_xml_get_node_text(child)) == NULL) { error("No text of node %s[%d]", DATA_ELNAME(data), data->index); retVal = WS_ERR_XML_PARSING; goto DONE; } while (isspace(str[0])) str++; errno = 0; if (str[0] == 0) { if (ws_xml_find_attr_bool(child, XML_NS_SCHEMA_INSTANCE, XML_SCHEMA_NIL)) { goto ATTR; } error("absent value = %s", str); retVal = WS_ERR_XML_PARSING; goto DONE; } tmp = strtoll(str, &end, 10); if (errno) { error("strtoul(%s) failed; errno = %d", str, errno); retVal = WS_ERR_XML_PARSING; goto DONE; } while (isspace(end[0])) end++; if (*end != 0) { error("wrong token = %s.", str); retVal = WS_ERR_XML_PARSING; goto DONE; } if (valSize == 1) { if (tmp > 127 || tmp < -128) { error("not int8 = %ld", tmp); retVal = WS_ERR_XML_PARSING; goto DONE; } *((XML_TYPE_INT8 *) data->elementBuf) = (XML_TYPE_INT8) tmp; } else if (valSize == 2) { if (tmp > 32767 || tmp < -32768) { error("not int16 = %ld", tmp); retVal = WS_ERR_XML_PARSING; goto DONE; } *((XML_TYPE_INT16 *) data->elementBuf) = (XML_TYPE_INT16) tmp; } else if (valSize == 4) { *((XML_TYPE_INT32 *) data->elementBuf) = (XML_TYPE_INT32) tmp; } else if (valSize == 8) { *((XML_TYPE_INT64 *) data->elementBuf) = (XML_TYPE_INT64) tmp; } else { error("unsupported int size + %d", 8 * valSize); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } } ATTR: handle_attrs(data, child, valSize); DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data); } if ((data->mode == XML_SMODE_DESERIALIZE) && xml_serializer_get_child(data)) { error("too many (%d > %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } DONE: TRACE_EXIT; return retVal; } static int do_serialize_uint(XmlSerializationData * data, int valSize) { WsXmlNodeH child = NULL; XML_TYPE_UINT64 tmp; int retVal = DATA_ALL_SIZE(data); char *end; char *str; TRACE_ENTER; debug("handle %d UINT%d %s;", DATA_COUNT(data), 8 * valSize, data->elementInfo->name); if (DATA_BUF(data) + retVal > data->stopper) { error("size of %d structures %s exceeds stopper (%p > %p)", DATA_COUNT(data), DATA_ELNAME(data), DATA_BUF(data) + retVal, data->stopper); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) { DATA_BUF(data) = DATA_BUF(data) + retVal; goto DONE; } if ((data->mode != XML_SMODE_DESERIALIZE && data->mode != XML_SMODE_SERIALIZE)) { error("invalid mode %d", data->mode); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } for (data->index = 0; data->index < DATA_COUNT(data); data->index++) { debug("%s[%d] = %p", data->elementInfo->name, data->index, data->elementBuf); if (data->mode == XML_SMODE_SERIALIZE) { debug("value size: %d", valSize); if (valSize == 1) tmp = *((XML_TYPE_UINT8 *) data->elementBuf); else if (valSize == 2) tmp = *((XML_TYPE_UINT16 *) data-> elementBuf); else if (valSize == 4) tmp = *((XML_TYPE_UINT32 *) data-> elementBuf); else if (valSize == 8) tmp = *((XML_TYPE_UINT64 *) data-> elementBuf); else { error("unsupported uint size + %d", 8 * valSize); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (((child = xml_serializer_add_child(data, NULL)) == NULL) || (ws_xml_set_node_ulong(child, tmp)) != 0) { debug("could not add child %s[%d]", DATA_ELNAME(data), data->index); retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } } if (data->mode == XML_SMODE_DESERIALIZE) { if ((child = xml_serializer_get_child(data)) == NULL) { error ("not enough (%d < %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } if ((str = ws_xml_get_node_text(child)) == NULL) { error("No text of node %s[%d]", DATA_ELNAME(data), data->index); retVal = WS_ERR_XML_PARSING; goto DONE; } while (isspace(str[0])) str++; errno = 0; if (str[0] == '-' || str[0] == 0) { if (ws_xml_find_attr_bool(child, XML_NS_SCHEMA_INSTANCE, XML_SCHEMA_NIL)) { goto ATTR; } error("absent value = %s", str); retVal = WS_ERR_XML_PARSING; goto DONE; } tmp = strtoull(str, &end, 10); if (errno) { error("strtoul(%s) failed; errno = %d", str, errno); retVal = WS_ERR_XML_PARSING; goto DONE; } while (isspace(end[0])) end++; if (*end != 0) { error("wrong token = %s.", str); retVal = WS_ERR_XML_PARSING; goto DONE; } if (valSize == 1) { if (tmp > 255) { error("not uint8 = %ld", tmp); retVal = WS_ERR_XML_PARSING; goto DONE; } *((XML_TYPE_UINT8 *) data->elementBuf) = (XML_TYPE_UINT8) tmp; } else if (valSize == 2) { if (tmp > 65535) { error("not uint16 = %ld", tmp); retVal = WS_ERR_XML_PARSING; goto DONE; } *((XML_TYPE_UINT16 *) data->elementBuf) = (XML_TYPE_UINT16) tmp; } else if (valSize == 4) { *((XML_TYPE_UINT32 *) data->elementBuf) = (XML_TYPE_UINT32) tmp; } else if (valSize == 8) { *((XML_TYPE_UINT64 *) data->elementBuf) = (XML_TYPE_UINT64) tmp; } else { error("unsupported uint size + %d", 8 * valSize); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } } ATTR: handle_attrs(data, child, valSize); DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data); } if ((data->mode == XML_SMODE_DESERIALIZE) && xml_serializer_get_child(data)) { error("too many (%d > %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } DONE: TRACE_EXIT; return retVal; } int do_serialize_uint8(XmlSerializationData * data) { if (XML_IS_ATTRS(data->elementInfo)) { size_t al = get_struct_align(); size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; } return do_serialize_uint(data, sizeof(XML_TYPE_UINT8)); } int do_serialize_uint16(XmlSerializationData * data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_UINT16 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_uint(data, sizeof(XML_TYPE_UINT16)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_uint32(XmlSerializationData * data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_UINT32 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_uint(data, sizeof(XML_TYPE_UINT32)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_uint64(XmlSerializationData * data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_UINT64 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_uint(data, sizeof(XML_TYPE_UINT64)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_int8(struct __XmlSerializationData* data) { if (XML_IS_ATTRS(data->elementInfo)) { size_t al = get_struct_align(); size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; } return do_serialize_int(data, sizeof(XML_TYPE_INT8)); } int do_serialize_int16(struct __XmlSerializationData* data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_UINT16 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_int(data, sizeof(XML_TYPE_INT16)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_int32(struct __XmlSerializationData* data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_UINT32 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_int(data, sizeof(XML_TYPE_INT32)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_int64(struct __XmlSerializationData* data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_UINT64 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_int(data, sizeof(XML_TYPE_INT64)); if (retVal >= 0) { retVal += pad; } return retVal; } static int do_serialize_real(XmlSerializationData * data, int valSize) { WsXmlNodeH child = NULL; XML_TYPE_REAL64 tmp; int retVal = DATA_ALL_SIZE(data); char *end; char *str; TRACE_ENTER; debug("handle %d REAL%d %s;", DATA_COUNT(data), 8 * valSize, data->elementInfo->name); if (DATA_BUF(data) + retVal > data->stopper) { error("size of %d structures %s exceeds stopper (%p > %p)", DATA_COUNT(data), DATA_ELNAME(data), DATA_BUF(data) + retVal, data->stopper); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) { DATA_BUF(data) = DATA_BUF(data) + retVal; goto DONE; } if ((data->mode != XML_SMODE_DESERIALIZE && data->mode != XML_SMODE_SERIALIZE)) { error("invalid mode %d", data->mode); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } for (data->index = 0; data->index < DATA_COUNT(data); data->index++) { debug("%s[%d] = %p", data->elementInfo->name, data->index, data->elementBuf); if (data->mode == XML_SMODE_SERIALIZE) { debug("value size: %d", valSize); if (valSize == 4) tmp = *((XML_TYPE_REAL32 *) data-> elementBuf); else if (valSize == 8) tmp = *((XML_TYPE_REAL64 *) data-> elementBuf); else { error("unsupported real size + %d", 8 * valSize); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (((child = xml_serializer_add_child(data, NULL)) == NULL) || (ws_xml_set_node_real(child, tmp)) != 0) { debug("could not add child %s[%d]", DATA_ELNAME(data), data->index); retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } } if (data->mode == XML_SMODE_DESERIALIZE) { if ((child = xml_serializer_get_child(data)) == NULL) { error ("not enough (%d < %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } if ((str = ws_xml_get_node_text(child)) == NULL) { error("No text of node %s[%d]", DATA_ELNAME(data), data->index); retVal = WS_ERR_XML_PARSING; goto DONE; } while (isspace(str[0])) str++; errno = 0; if (str[0] == 0) { if (ws_xml_find_attr_bool(child, XML_NS_SCHEMA_INSTANCE, XML_SCHEMA_NIL)) { goto ATTR; } error("absent value = %s", str); retVal = WS_ERR_XML_PARSING; goto DONE; } tmp = strtod(str, &end); if (errno) { error("strtod(%s) failed; errno = %d", str, errno); retVal = WS_ERR_XML_PARSING; goto DONE; } while (isspace(end[0])) end++; if (*end != 0) { error("wrong token = %s.", str); retVal = WS_ERR_XML_PARSING; goto DONE; } if (valSize == 4) { *((XML_TYPE_REAL32 *) data->elementBuf) = (XML_TYPE_REAL32) tmp; } else if (valSize == 8) { *((XML_TYPE_REAL64 *) data->elementBuf) = (XML_TYPE_REAL64) tmp; } else { error("unsupported REAL size + %d", 8 * valSize); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } } ATTR: handle_attrs(data, child, valSize); DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data); } if ((data->mode == XML_SMODE_DESERIALIZE) && xml_serializer_get_child(data)) { error("too many (%d > %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } DONE: TRACE_EXIT; return retVal; } int do_serialize_real32(struct __XmlSerializationData* data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_REAL32 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_real(data, sizeof(XML_TYPE_REAL32)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_real64(struct __XmlSerializationData* data) { typedef struct { XML_TYPE_UINT8 a; XML_TYPE_REAL64 b; } dummy; size_t al; size_t pad; int retVal; if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } DATA_BUF(data) = DATA_BUF(data) + pad; retVal = do_serialize_real(data, sizeof(XML_TYPE_REAL64)); if (retVal >= 0) { retVal += pad; } return retVal; } int do_serialize_string(XmlSerializationData * data) { WsXmlNodeH child = NULL; int retVal = DATA_ALL_SIZE(data); size_t al; size_t pad; typedef struct { XML_TYPE_UINT8 a; XML_TYPE_STR b; } dummy; TRACE_ENTER; debug("handle %d strings %s = %p", DATA_COUNT(data), data->elementInfo->name, data->elementBuf); if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } retVal += pad; if (DATA_BUF(data) + retVal > data->stopper) { error("stopper: %p > %p", DATA_BUF(data) + retVal, data->stopper); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data)) { data->elementBuf = DATA_BUF(data) + retVal; goto DONE; } DATA_BUF(data) = DATA_BUF(data) + pad; debug("adjusted elementBuf = %p", data->elementBuf); for (data->index = 0; data->index < DATA_COUNT(data); data->index++) { if (data->mode == XML_SMODE_FREE_MEM) { xml_serializer_free(data, *(XML_TYPE_STR *) DATA_BUF(data)); *(XML_TYPE_STR *) DATA_BUF(data) = NULL; } else if (data->mode == XML_SMODE_SERIALIZE) { char *valPtr = *((char **) DATA_BUF(data)); child = xml_serializer_add_child(data, valPtr); if (child == NULL) { error("xml_serializer_add_child failed."); retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } if (ws_xml_get_node_text(child) == NULL) { ws_xml_add_node_attr(child, XML_NS_SCHEMA_INSTANCE, XML_SCHEMA_NIL, "true"); } } else if (data->mode == XML_SMODE_DESERIALIZE) { char *src; if ((child = xml_serializer_get_child(data)) == NULL) { error ("not enough (%d < %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } src = ws_xml_get_node_text(child); if (src != NULL && *src != 0) { char *dstPtr; int dstSize = 1 + strlen(src); dstPtr = (char *) xml_serializer_alloc(data, dstSize, 1); if (dstPtr == NULL) { error("no memory"); retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } strncpy(dstPtr, src, dstSize); *((XML_TYPE_PTR *) DATA_BUF(data)) = dstPtr; } } else { error("invalid mode"); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } handle_attrs(data, child, sizeof(XML_TYPE_STR)); DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data); } if ((data->mode == XML_SMODE_DESERIALIZE) && xml_serializer_get_child(data)) { error("too many (%d > %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } DONE: TRACE_EXIT; return retVal; } int do_serialize_bool(XmlSerializationData * data) { int retVal = DATA_ALL_SIZE(data); typedef struct { XML_TYPE_UINT8 a; XML_TYPE_BOOL b; } dummy; size_t al; size_t pad; WsXmlNodeH child = NULL; TRACE_ENTER; debug("handle %d booleans %s; ptr = %p", DATA_COUNT(data), DATA_ELNAME(data), DATA_BUF(data)); if (XML_IS_ATTRS(data->elementInfo)) { al = get_struct_align(); } else { al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; } pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } retVal += pad; if (DATA_BUF(data) + retVal > data->stopper) { retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data) || data->mode == XML_SMODE_FREE_MEM) { data->elementBuf = DATA_BUF(data) + retVal; goto DONE; } DATA_BUF(data) = DATA_BUF(data) + pad; debug("adjusted elementBuf = %p", data->elementBuf); for (data->index = 0; data->index < DATA_COUNT(data); data->index++) { debug("%s[%d] = %p", DATA_ELNAME(data), data->index, DATA_BUF(data)); if (data->mode == XML_SMODE_SERIALIZE) { XML_TYPE_BOOL tmp; tmp = *((XML_TYPE_BOOL *) DATA_BUF(data)); if ((child = xml_serializer_add_child(data, (tmp == 0) ? "false" : "true")) == NULL) { retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } } else if (data->mode == XML_SMODE_DESERIALIZE) { XML_TYPE_PTR dataPtr = (XML_TYPE_PTR) DATA_BUF(data); XML_TYPE_BOOL tmp = -1; char *src; if ((child = xml_serializer_get_child(data)) == NULL) { error("not enough (%d < %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } src = ws_xml_get_node_text(child); if (src == NULL || *src == 0) { tmp = 1; } else { if (isdigit(*src)) { tmp = atoi(src); } else { if (strcmp(src, "yes") == 0 || strcmp(src, "true") == 0) { tmp = 1; } else if (strcmp(src, "no") == 0 || strcmp(src, "false") == 0) { tmp = 0; } } } if (tmp == 0 || tmp == 1) { *((XML_TYPE_BOOL *) dataPtr) = tmp; } else { retVal = WS_ERR_XML_PARSING; goto DONE; } } else { retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } handle_attrs(data, child, sizeof(XML_TYPE_BOOL)); DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data); } if ((data->mode == XML_SMODE_DESERIALIZE) && xml_serializer_get_child(data)) { error("too many (%d > %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } DONE: TRACE_EXIT; return retVal; } static XmlSerialiseDynamicSizeData *make_dyn_size_data(XmlSerializationData * data, int * retValp) { XmlSerialiseDynamicSizeData *dyn = (XmlSerialiseDynamicSizeData *) data->elementBuf; int savedIndex = data->index; int size; TRACE_ENTER; data->index = 0; while (xml_serializer_get_child(data) != NULL) { data->index++; } dyn->count = data->index; data->index = savedIndex; if (dyn->count < DATA_MIN_COUNT(data)) { error("not enough (%d < %d) elements %s", dyn->count, DATA_MIN_COUNT(data), DATA_ELNAME(data)); *retValp = WS_ERR_XML_PARSING; dyn = NULL; goto DONE; } if ((DATA_MAX_COUNT(data) > 0) && dyn->count > DATA_MAX_COUNT(data)) { error("too many (%d > %d) elements %s", dyn->count, DATA_MAX_COUNT(data), DATA_ELNAME(data)); *retValp = WS_ERR_XML_PARSING; dyn = NULL; goto DONE; } debug("count = %d of %d sizes", dyn->count, DATA_SIZE(data)); if (dyn->count == 0) { goto DONE; } size = DATA_SIZE(data) * dyn->count; dyn->data = xml_serializer_alloc(data, size, 1); if (dyn->data == NULL) { error("no memory"); *retValp = WS_ERR_INSUFFICIENT_RESOURCES; dyn = NULL; } DONE: TRACE_EXIT; return dyn; } int do_serialize_dyn_size_array(XmlSerializationData * data) { typedef struct { char a; XmlSerialiseDynamicSizeData b; } dummy; size_t al = (char *) &(((dummy *) NULL)->b) - (char *) NULL; size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); int retVal; char *savedBufPtr; XmlSerializerInfo *savedElementInfo; XmlSerialiseDynamicSizeData *dyn = NULL; int tmp; XmlSerializerInfo myinfo; int savedIndex; char *savedStopper; TRACE_ENTER; debug("Dyn size array %s; ptr = %p", data->elementInfo->name, data->elementBuf); if (pad) pad = al - pad; retVal = DATA_SIZE(data) + pad; if (DATA_BUF(data) + retVal > data->stopper) { retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data)) { DATA_BUF(data) = DATA_BUF(data) + retVal; goto DONE; } DATA_BUF(data) = DATA_BUF(data) + pad; debug("adjusted elementBuf = %p", data->elementBuf); savedBufPtr = DATA_BUF(data); savedElementInfo = data->elementInfo; if (data->mode != XML_SMODE_SERIALIZE && data->mode != XML_SMODE_DESERIALIZE && data->mode != XML_SMODE_FREE_MEM) { retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (data->mode == XML_SMODE_DESERIALIZE) { if ((dyn = make_dyn_size_data(data, &retVal)) == NULL) { goto DONE; } } else { dyn = (XmlSerialiseDynamicSizeData *) data->elementBuf; if (data->mode == XML_SMODE_SERIALIZE) { if (dyn->count < DATA_MIN_COUNT(data)) { error("not enough (%d < %d) elements %s", dyn->count, DATA_MIN_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } if ((DATA_MAX_COUNT(data) > 0) && dyn->count > DATA_MAX_COUNT(data)) { error("too many (%d > %d) elements %s", dyn->count, DATA_MAX_COUNT(data), DATA_ELNAME(data)); retVal = WS_ERR_XML_PARSING; goto DONE; } } } if (dyn->count == 0) { // no dynamic data. nothing to do goto DONE; } savedIndex = data->index; savedStopper = data->stopper; memcpy(&myinfo, savedElementInfo->extData, sizeof(XmlSerializerInfo)); myinfo.count = dyn->count; myinfo.name = data->elementInfo->name; myinfo.ns = data->elementInfo->ns; data->stopper = (char *) dyn->data + DATA_SIZE(data) * dyn->count; data->elementInfo = &myinfo; DATA_BUF(data) = dyn->data; data->index = 0; debug("dyn = %p, dyn->data = %p + 0x%x", dyn, dyn->data, DATA_SIZE(data) * dyn->count); tmp = data->elementInfo->proc(data); data->index = savedIndex; DATA_BUF(data) = savedBufPtr; data->elementInfo = savedElementInfo; data->stopper = savedStopper; if (tmp < 0 && data->mode != XML_SMODE_FREE_MEM) { retVal = tmp; goto DONE; } if ((data->mode == XML_SMODE_FREE_MEM) && dyn->data) { xml_serializer_free(data, dyn->data); goto DONE; } DONE: DATA_BUF(data) = DATA_BUF(data) + DATA_SIZE(data); TRACE_EXIT; return retVal; } int do_serialize_struct(XmlSerializationData * data) { int retVal = 0; int i; int elementCount = 0; XmlSerializerInfo *elements = (XmlSerializerInfo *) data->elementInfo->extData; WsXmlNodeH savedXmlNode = data->xmlNode; XmlSerializerInfo *savedElement = data->elementInfo; int savedMode = data->mode; int savedIndex = data->index; void *savedStopper = data->stopper; size_t al = get_struct_align(); size_t pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); size_t count; size_t struct_size; int savedLocalIndex; char *savedLocalElementBuf; WsXmlNodeH child; TRACE_ENTER; debug("handle %d structure \"%s\" ptr = %p", DATA_COUNT(data), data->elementInfo->name ? data->elementInfo->name : "NULL", data->elementBuf); if (data->mode != XML_SMODE_SERIALIZE && data->mode != XML_SMODE_DESERIALIZE && data->mode != XML_SMODE_FREE_MEM) { retVal = WS_ERR_INVALID_PARAMETER; debug("Incorrect data->mode = %d", data->mode); goto DONE; } al = get_struct_align(); pad = (size_t) ((PTRTOINT) DATA_BUF(data) % al); if (pad) { pad = al - pad; } retVal = pad + XML_IS_HEAD(savedElement) ? DATA_SIZE(data) : DATA_ALL_SIZE(data); if ((char *) DATA_BUF(data) + retVal > data->stopper) { error("size of %d structures \"%s\" exceeds stopper (%p > %p)", DATA_COUNT(data), DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL", (char *) DATA_BUF(data) + retVal, data->stopper); retVal = WS_ERR_INVALID_PARAMETER; goto DONE; } if (DATA_MUST_BE_SKIPPED(data)) { debug(" %d elements %s skipped", DATA_COUNT(data), DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL"); DATA_BUF(data) = DATA_BUF(data) + retVal; goto DONE; } DATA_BUF(data) = DATA_BUF(data) + pad; debug("adjusted ptr= %p", data->elementBuf); while (elements[elementCount].proc != NULL) { elementCount++; } count = DATA_COUNT(data); struct_size = DATA_SIZE(data); if (XML_IS_HEAD(savedElement)) { count = data->index + 1; } else { data->index = 0; } for (; data->index < count; data->index++) { int tmp; child = NULL; savedLocalIndex = data->index; savedLocalElementBuf = DATA_BUF(data); data->stopper = savedLocalElementBuf + DATA_SIZE(data); debug("%s[%d] = %p", DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL", data->index, DATA_BUF(data)); if (data->mode == XML_SMODE_SERIALIZE) { child = xml_serializer_add_child(data, NULL); data->xmlNode = child; if (data->xmlNode == NULL) { error("cant add child"); retVal = WS_ERR_INSUFFICIENT_RESOURCES; goto DONE; } } else if (data->mode == XML_SMODE_DESERIALIZE) { child = xml_serializer_get_child(data); if (child == NULL) { error ("not enough (%d < %d) instances of element %s", data->index, DATA_COUNT(data), DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL"); retVal = WS_ERR_XML_PARSING; goto DONE; } data->xmlNode = child; } debug("before for loop. Struct %s = %p", savedElement->name ? savedElement->name : "NULL", DATA_BUF(data)); for (i = 0; retVal > 0 && i < elementCount; i++) { data->elementInfo = &elements[i]; debug ("handle %d elements %s of struct %s. dstPtr = %p", DATA_COUNT(data), DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL", savedElement->name ? savedElement->name : "NULL", DATA_BUF(data)); if (XML_IS_SKIP(data->elementInfo)) { data->mode = XML_SMODE_SKIP; } tmp = data->elementInfo->proc(data); debug("retval: %d", tmp); if (tmp < 0) { error("handling of element \"%s\" failed = %d", DATA_ELNAME(data) ? DATA_ELNAME(data) : "NULL", tmp); retVal = tmp; goto DONE; } } data->elementInfo = savedElement; data->index = savedLocalIndex; data->mode = savedMode; data->xmlNode = savedXmlNode; data->elementInfo = savedElement; handle_attrs(data, child, 0); data->elementBuf = savedLocalElementBuf + struct_size; } DONE: data->stopper = savedStopper; data->elementInfo = savedElement; data->index = savedIndex; data->mode = savedMode; data->xmlNode = savedXmlNode; TRACE_EXIT; return retVal; } static void initialize_xml_serialization_data(XmlSerializationData * data, WsSerializerContextH serctx, XmlSerializerInfo * elementInfo, XML_TYPE_PTR dataBuf, int mode, XML_NODE_ATTR * attrs, WsXmlNodeH xmlNode) { debug("Initialize XML Serialization..."); TRACE_ENTER; memset(data, 0, sizeof(XmlSerializationData)); data->serctx = serctx; data->elementInfo = elementInfo; data->elementBuf = dataBuf; data->mode = mode; data->attrs = attrs; data->xmlNode = xmlNode; debug("Finished initializing XML Serialization..."); TRACE_EXIT; return; } int ws_serialize(WsSerializerContextH serctx, WsXmlNodeH xmlNode, XML_TYPE_PTR dataPtr, XmlSerializerInfo * info, const char *name, const char *ns, XML_NODE_ATTR * attrs, int output) { int retVal = WS_ERR_INSUFFICIENT_RESOURCES; XmlSerializerInfo myinfo; XmlSerializationData data; TRACE_ENTER; if (info->proc == NULL) { error("info->proc == NULL"); goto DONE; } memcpy(&myinfo, info, sizeof(XmlSerializerInfo)); if (name == NULL) { error("name == NULL"); goto DONE; } myinfo.name = name; myinfo.ns = ns; myinfo.flags |= SER_HEAD; initialize_xml_serialization_data(&data, serctx, &myinfo, dataPtr, XML_SMODE_SERIALIZE, attrs, xmlNode); data.stopper = (char *) dataPtr + myinfo.size; if (output) { data.skipFlag = SER_IN; } else { data.skipFlag = SER_OUT; } retVal = myinfo.proc(&data); DONE: TRACE_EXIT; return retVal; } int ws_serializer_free_mem(WsSerializerContextH serctx, XML_TYPE_PTR buf, XmlSerializerInfo * info) { int retVal; XmlSerializationData data; XmlSerializerInfo myinfo; TRACE_ENTER; memcpy(&myinfo, info, sizeof(XmlSerializerInfo)); myinfo.flags |= SER_HEAD; initialize_xml_serialization_data(&data, serctx, &myinfo, buf, XML_SMODE_FREE_MEM, NULL, NULL); data.stopper = (char *) buf + myinfo.size; if ((retVal = info->proc(&data)) >= 0) { xml_serializer_free(&data, buf); } TRACE_EXIT; return retVal; } void *ws_deserialize(WsSerializerContextH serctx, WsXmlNodeH xmlParent, XmlSerializerInfo * info, const char *name, const char *ns, XML_NODE_ATTR ** attrs, int index, int output) { int size; void *retPtr = NULL; XmlSerializationData data; XmlSerializerInfo myinfo; TRACE_ENTER; memcpy(&myinfo, info, sizeof(XmlSerializerInfo)); if (name == NULL) { error("name == NULL"); } myinfo.name = name; myinfo.ns = ns; myinfo.flags |= SER_HEAD; initialize_xml_serialization_data(&data, serctx, &myinfo, NULL, XML_SMODE_DESERIALIZE, NULL, xmlParent); data.index = index; if (output) { data.skipFlag = SER_IN; } else { data.skipFlag = SER_OUT; } size = myinfo.size; if ((data.elementBuf = xml_serializer_alloc(&data, size, 1)) != NULL) { retPtr = data.elementBuf; data.stopper = (char *) retPtr + size; if (myinfo.proc && myinfo.proc(&data) <= 0) { data.elementBuf = retPtr; retPtr = NULL; ws_serializer_free_mem(serctx, data.elementBuf, &myinfo); error("Error during serialization"); } } TRACE_EXIT; return retPtr; } static void enforce_mustunderstand(WsXmlNodeH node) { WsXmlDocH doc = ws_xml_get_node_doc(node); char *ns = ws_xml_get_node_name_ns(ws_xml_get_doc_root(doc)); ws_xml_add_node_attr(node, ns, SOAP_MUST_UNDERSTAND, "true"); } int ws_serialize_str(WsSerializerContextH serctx, WsXmlNodeH parent, const char *str, const char *nameNs, const char *name, int mustunderstand) { WsXmlNodeH node; TRACE_ENTER; //printf("mustunderstand flag for %s: %d\n", name, mustunderstand ); node = ws_xml_add_child(parent, nameNs, name, str); if (node && mustunderstand) { enforce_mustunderstand(node); } TRACE_EXIT; return (node == NULL); } int ws_serialize_uint32(WsSerializerContextH serctx, WsXmlNodeH parent, unsigned long val, const char *nameNs, const char *name, int mustunderstand) { WsXmlNodeH node = ws_xml_add_child(parent, nameNs, name, NULL); TRACE_ENTER; if (node) { ws_xml_set_node_ulong(node, val); if (mustunderstand) { enforce_mustunderstand(node); } } TRACE_EXIT; return (node == NULL); } char *ws_deserialize_str(WsSerializerContextH serctx, WsXmlNodeH parent, int index, const char *nameNs, const char *name) { char *str = NULL; WsXmlNodeH node = ws_xml_get_child(parent, index, nameNs, name); TRACE_ENTER; if (node) { str = ws_xml_get_node_text(node); if (serctx && str) { int len = (int )strlen(str) + 1; char *tmp = str; if ((str = ws_serializer_alloc(serctx, len * sizeof(char)))) strcpy(str, tmp); } } TRACE_EXIT; return str; } unsigned long ws_deserialize_uint32(WsSerializerContextH serctx, WsXmlNodeH parent, int index, const char *nameNs, const char *name) { unsigned long val = 0; WsXmlNodeH node = ws_xml_get_child(parent, index, nameNs, name); TRACE_ENTER; if (node) { val = ws_xml_get_node_ulong(node); } TRACE_EXIT; return val; } /* * Returns duration in seconds in argument * * the format of OperationTimeout is defined by the * XML Schema Datatypes Section 3.2.6.1 http://www.w3.org/TR/xmlschema-2/ * * Sample: P0Y0M0DT0H0M60.00S * * (must start with 'P', 'T' separated date from time, seconds may have fraction) * * FIXME: handle fractions of seconds (don't return a time_t but a struct timeval) * */ int ws_deserialize_duration(const char *t, time_t * value) { long years = 0; long months = 0; long days = 0; long hours = 0; long mins = 0; long secs = 0; time_t vs; int v; double f; /* float for fractional second */ char *e; /* end pointer for strtol */ int got = 64; /* bitmask of parsing position, 64==year */ int res = 1; /* final result, 1 == error */ int time_handeled = 0; /* seen 'T' */ int negative = 0; TRACE_ENTER; if (t == NULL) { debug("node text == NULL"); goto DONE; } if (*t == '-') { negative = 1; t++; } if (*t != 'P') { debug("Wrong begining of duration"); goto DONE; } while (*++t) { if (*t == 'T') { time_handeled = 1; continue; } v = strtol(t, &e, 10); if (t == e) { debug("wrong format, missing numeric value"); goto DONE; } if (time_handeled && (*e == '.')) { f = strtod(t, &e); if (*e != 'S') { debug("float but not secs"); goto DONE; } if (((int)floor(f+0.5)) > v) { v++; /* round value up */ } } switch (*e) { case 'Y': if (got <= 32 || time_handeled) { debug("wrong order Y"); goto DONE; } years = v; got = 32; break; case 'M': if (!time_handeled) { // months if (got <= 16) { debug("wrong order M"); goto DONE; } months = v; got = 16; break; } // minutes if (got <= 2 || !time_handeled) { debug("wrong order M"); goto DONE; } mins = v; got = 2; break; case 'D': if (got <= 8 || time_handeled) { debug("wrong order D"); goto DONE; } days = v; got = 8; break; case 'H': if (got <= 4 || !time_handeled) { debug("wrong order H"); goto DONE; } hours = v; got = 4; break; case 'S': if (got <= 1 || !time_handeled) { debug("wrong order S"); goto DONE; } secs = v; got = 1; break; default: debug("wrong format %c", *e); goto DONE; } t = e; } // invalid if T found and no HMS, or no time value detected if ((time_handeled && (got > 4)) || (64 == got)){ debug("wrong format: floating T or no time value detected"); goto DONE; } // We don't know exact date and time of the sender. // For simplicity comsider 1 month = 30days; vs = secs + 60 * mins + 60 * 60 * hours + 60 * 60 * 24 * days + 60 * 60 * 24 * 30 * months + 60 * 60 * 24 * 30 * 12 * years; if (negative) { vs = 0 - vs; } *value = vs; res = 0; // good at this point DONE: TRACE_EXIT; return res; } int ws_deserialize_datetime(const char *text, XML_DATETIME * tmx) { int res = 0; int r; int hours; int mins; struct tm tm; time_t t; TRACE_ENTER; if (text == NULL) { debug("node text == NULL"); res = 1; goto DONE; } bzero(tmx, sizeof(XML_DATETIME)); r = sscanf(text, "%u-%u-%uT%u:%u:%u%d:%u", &tmx->tm.tm_year, &tmx->tm.tm_mon, &tmx->tm.tm_mday, &tmx->tm.tm_hour, &tmx->tm.tm_min, &tmx->tm.tm_sec, &hours, &mins); if (r != 8) { debug("wrong body of datetime(%d): %s", r, text); res = 1; goto DONE; } tmx->tm.tm_year -= 1900; tmx->tm.tm_mon -= 1; t = time(NULL); #ifdef _WIN32 localtime_s(&tm, &t); #else localtime_r(&t, &tm); #endif tmx->tm.tm_isdst = tm.tm_isdst; if (hours < 0) { tmx->tz_min = 60 * hours - mins; } else { tmx->tz_min = 60 * hours + mins; } DONE: return res; } void *ws_serializer_alloc(WsSerializerContextH serctx, int size) { WsSerializerMemEntry *ptr = NULL; TRACE_ENTER; if ((ptr = (WsSerializerMemEntry *) u_malloc(sizeof(WsSerializerMemEntry) + size)) != NULL) { lnode_t *node; u_lock(serctx); if ((node = lnode_create(ptr)) == NULL) { u_free(ptr); ptr = NULL; } else { list_append(serctx->WsSerializerAllocList, node); } u_unlock(serctx); } TRACE_EXIT; return ptr ? ptr->buf : NULL; } static int do_serializer_free(WsSerializerContextH serctx, void *ptr) { lnode_t *node = NULL; lnode_t *node2 = NULL; TRACE_ENTER; if (serctx) { u_lock(serctx); node = list_first(serctx->WsSerializerAllocList); while (node != NULL) { WsSerializerMemEntry *entry = (WsSerializerMemEntry *) node->list_data; if (entry && (!ptr || ptr == entry->buf)) { u_free(entry); node2 = node; node = list_delete2(serctx->WsSerializerAllocList, node); lnode_destroy (node2); if (ptr != NULL) { break; } } else node = list_next(serctx->WsSerializerAllocList, node); } u_unlock(serctx); } TRACE_EXIT; return (node != NULL); } int ws_serializer_free(WsSerializerContextH serctx, void *ptr) { int retVal = 0; TRACE_ENTER; if (ptr != NULL) retVal = do_serializer_free(serctx, ptr); TRACE_EXIT; return retVal; } void ws_serializer_free_all(WsSerializerContextH serctx) { TRACE_ENTER; do_serializer_free(serctx, NULL); TRACE_EXIT; } int ws_havenilvalue(XML_NODE_ATTR *attrs) { while(attrs) { if(attrs->ns && attrs->name && attrs->value && strcmp(attrs->ns, XML_NS_SCHEMA_INSTANCE) == 0 && strcmp(attrs->name, XML_SCHEMA_NIL) == 0 && strcasecmp(attrs->value, "true") == 0) return 1; attrs = attrs->next; } return 0; }