head 1.14; access; symbols XDS_0_9_3:1.14 XDS_0_9_2:1.14 XDS_0_9_1:1.13 XDS_0_9_0:1.11; locks; strict; comment @ * @; 1.14 date 2005.06.02.18.51.44; author rse; state Exp; branches; next 1.13; 1.13 date 2004.09.12.17.32.14; author rse; state Exp; branches; next 1.12; 1.12 date 2004.09.12.17.20.36; author rse; state Exp; branches; next 1.11; 1.11 date 2003.02.17.12.36.02; author rse; state Exp; branches; next 1.10; 1.10 date 2002.03.17.10.25.53; author rse; state Exp; branches; next 1.9; 1.9 date 2002.01.02.17.13.44; author rse; state Exp; branches; next 1.8; 1.8 date 2001.08.30.14.49.49; author simons; state Exp; branches; next 1.7; 1.7 date 2001.08.13.19.48.02; author rse; state Exp; branches; next 1.6; 1.6 date 2001.08.12.11.31.45; author rse; state Exp; branches; next 1.5; 1.5 date 2001.08.09.21.05.18; author rse; state Exp; branches; next 1.4; 1.4 date 2001.08.09.20.59.05; author rse; state Exp; branches; next 1.3; 1.3 date 2001.08.09.19.58.35; author rse; state Exp; branches; next 1.2; 1.2 date 2001.08.08.19.32.02; author rse; state Exp; branches; next 1.1; 1.1 date 2001.08.08.19.15.23; author rse; state Exp; branches; next ; desc @@ 1.14 log @Bumped year in copyright messages for year 2005. @ text @/* ** OSSP xds - Extensible Data Serialization ** Copyright (c) 2001-2005 Ralf S. Engelschall ** Copyright (c) 2001-2005 The OSSP Project ** Copyright (c) 2001-2005 Cable & Wireless ** ** This file is part of OSSP xds, an extensible data serialization ** library which can be found at http://www.ossp.org/pkg/lib/xds/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** 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. ** ** xds_engine_xml.c: XML encoding/decoding engine */ #include #include #include #include "xds.h" /* * Encode/decode XML document framework */ static const char xds_xml_begin_text[] = "\n" "\n" "\n"; static const char xds_xml_end_text[] = "\n"; int xml_encode_begin(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_init_encoding_engine(strlen(xds_xml_begin_text)); memmove(buffer, xds_xml_begin_text, strlen(xds_xml_begin_text)); return XDS_OK; } int xml_decode_begin(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_init_encoding_engine(strlen(xds_xml_begin_text)); if (strncasecmp(buffer, xds_xml_begin_text, strlen(xds_xml_begin_text)) != 0) return XDS_ERR_TYPE_MISMATCH; return XDS_OK; } int xml_encode_end(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_init_encoding_engine(strlen(xds_xml_end_text)); memmove(buffer, xds_xml_end_text, strlen(xds_xml_end_text)); return XDS_OK; } int xml_decode_end(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_init_decoding_engine(strlen(xds_xml_end_text)); if (strncasecmp(buffer, xds_xml_end_text, strlen(xds_xml_end_text)) != 0) return XDS_ERR_TYPE_MISMATCH; return XDS_OK; } /* * Encode/decode signed 32-bit integer values. */ int xml_encode_int32(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_int32_t value; char buf[32]; size_t i, j; char *p; int negative; xds_init_encoding_engine(7 + 8 + 11); /* Get the value and format it into our buffer. Keep track of the length of the formatted result. */ value = va_arg(*args, xds_int32_t); if (value < 0) { negative = XDS_TRUE; value = 0 - value; } else negative = XDS_FALSE; i = 0; do { unsigned char remainder = value % 10; value = value / 10; buf[i++] = '0' + remainder; } while (value != 0); if (negative) buf[i++] = '-'; /* Now that we know the correct size of our data's representation, write it into the buffer. */ *used_buffer_size = 7 + 8 + i; p = buffer; memmove(p, "", 7); p += 7; for (j = i; j > 0;) *p++ = buf[--j]; memmove(p, "", 8); return XDS_OK; } int xml_decode_int32(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_int32_t *value; char *p; int negative; xds_init_decoding_engine(7 + 8 + 1); /* Does the opening XML tag match? */ if (strncasecmp(buffer, "", 7) != 0) return XDS_ERR_TYPE_MISMATCH; /* Decode the representation of the value. */ value = va_arg(*args, xds_int32_t *); *value = 0; p = (char *)buffer + 7; if (*p == '-') { negative = XDS_TRUE; p++; } else negative = XDS_FALSE; while (isdigit((int)*p)) { if (p >= (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; *value *= 10; *value += *p++ - '0'; } if (negative) *value = 0 - *value; /* Does the closing XML tag match? */ if (p + 8 > (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; else if (strncasecmp(p, "", 8) != 0) return XDS_ERR_TYPE_MISMATCH; *used_buffer_size = p + 8 - (char *)buffer; return XDS_OK; } /* * Encode/decode unsigned 32-bit integer values. */ int xml_encode_uint32(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_uint32_t value; char buf[32]; size_t i, j; char *p; xds_init_encoding_engine(8 + 9 + 10); /* Format value into our buffer. */ value = va_arg(*args, xds_uint32_t); i = 0; do { unsigned char remainder = value % 10; value = value / 10; buf[i++] = '0' + remainder; } while (value != 0); /* Store the correct buffer size. */ *used_buffer_size = 8 + 9 + i; /* Write result into the buffer. */ p = buffer; memmove(p, "", 8); p += 8; for (j = i; j > 0;) *p++ = buf[--j]; memmove(p, "", 9); return XDS_OK; } int xml_decode_uint32(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_uint32_t *value; char *p; xds_init_decoding_engine(8 + 9 + 1); /* Does the opening XML tag match? */ if (strncasecmp(buffer, "", 8) != 0) return XDS_ERR_TYPE_MISMATCH; /* Decode the representation of the value. */ value = va_arg(*args, xds_uint32_t *); *value = 0; p = (char *)buffer + 8; while (isdigit((int)*p)) { if (p >= (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; *value *= 10; *value += *p++ - '0'; } /* Does the closing XML tag match? */ if (p + 9 > (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; else if (strncasecmp(p, "", 9) != 0) return XDS_ERR_TYPE_MISMATCH; *used_buffer_size = p + 9 - (char *)buffer; return XDS_OK; } #ifdef XDS_HAVE_64_BIT_SUPPORT /* * Encode/decode signed 64-bit integer values. */ int xml_encode_int64(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_int64_t value; char buf[64]; size_t i, j; char *p; int negative; xds_init_encoding_engine(7 + 8 + 21); /* Format value into our buffer. */ value = va_arg(*args, xds_int64_t); if (value < 0) { negative = XDS_TRUE; value = 0 - value; } else negative = XDS_FALSE; i = 0; do { unsigned char remainder = value % 10; value = value / 10; buf[i++] = '0' + remainder; } while (value != 0); if (negative) buf[i++] = '-'; /* Store the correct buffer size. */ *used_buffer_size = 7 + 8 + i; /* Write result into the buffer. */ p = buffer; memmove(p, "", 7); p += 7; for (j = i; j > 0;) *p++ = buf[--j]; memmove(p, "", 8); return XDS_OK; } int xml_decode_int64(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_int64_t *value; char *p; int negative; xds_init_decoding_engine(7 + 8 + 1); /* Does the opening XML tag match? */ if (strncasecmp(buffer, "", 7) != 0) return XDS_ERR_TYPE_MISMATCH; /* Decode the representation of the value. */ value = va_arg(*args, xds_int64_t *); *value = 0; p = (char *)buffer + 7; if (*p == '-') { negative = XDS_TRUE; p++; } else negative = XDS_FALSE; while (isdigit((int)*p)) { if (p >= (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; *value *= 10; *value += *p++ - '0'; } if (negative) *value = 0 - *value; /* Does the closing XML tag match? */ if (p + 8 > (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; else if (strncasecmp(p, "", 8) != 0) return XDS_ERR_TYPE_MISMATCH; *used_buffer_size = p + 8 - (char *)buffer; return XDS_OK; } /* * Encode/decode unsigned 64-bit integer values. */ int xml_encode_uint64(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_uint64_t value; char buf[64]; size_t i, j; char *p; xds_init_encoding_engine(8 + 9 + 20); /* Format value into our buffer. */ value = va_arg(*args, xds_uint64_t); i = 0; do { unsigned char remainder = value % 10; value = value / 10; buf[i++] = '0' + remainder; } while (value != 0); /* Store the correct buffer size. */ *used_buffer_size = 8 + 9 + i; /* Write result into the buffer. */ p = buffer; memmove(p, "", 8); p += 8; for (j = i; j > 0;) *p++ = buf[--j]; memmove(p, "", 9); return XDS_OK; } int xml_decode_uint64(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_uint64_t *value; char *p; xds_init_decoding_engine(8 + 9 + 1); /* Does the opening XML tag match? */ if (strncasecmp(buffer, "", 8) != 0) return XDS_ERR_TYPE_MISMATCH; /* Decode the representation of the value. */ value = va_arg(*args, xds_uint64_t *); *value = 0; p = (char *)buffer + 8; while (isdigit((int)*p)) { if (p >= (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; *value *= 10; *value += *p++ - '0'; } /* Does the closing XML tag match? */ if (p + 9 > (char *)buffer + buffer_size) return XDS_ERR_UNDERFLOW; else if (strncasecmp(p, "", 9) != 0) return XDS_ERR_TYPE_MISMATCH; *used_buffer_size = p + 9 - (char *)buffer; return XDS_OK; } #endif /* XDS_HAVE_64_BIT_SUPPORT */ /* * Encode/decode floating point values. */ int xml_encode_float(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_init_encoding_engine(7 + 8 + 1); *used_buffer_size = snprintf(buffer, buffer_size, "%f", va_arg(*args, double)); if (*used_buffer_size >= buffer_size) return XDS_ERR_OVERFLOW; else return XDS_OK; } int xml_decode_float(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { int size; xds_init_decoding_engine(7 + 8 + 1); if (sscanf(buffer, "%f%n", va_arg(*args, float*), &size) != 1) return XDS_ERR_TYPE_MISMATCH; else { *used_buffer_size = size; return XDS_OK; } } /* * Encode/decode double-precision floating point values. */ int xml_encode_double(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_init_encoding_engine(8 + 9 + 1); *used_buffer_size = snprintf(buffer, buffer_size, "%f", va_arg(*args, double)); if (*used_buffer_size >= buffer_size) return XDS_ERR_OVERFLOW; else return XDS_OK; } int xml_decode_double(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { int size; xds_init_decoding_engine(8 + 9 + 1); if (sscanf(buffer, "%lf%n", va_arg(*args, double*), &size) != 1) return XDS_ERR_TYPE_MISMATCH; else { *used_buffer_size = size; return XDS_OK; } } /* * Encode/decode NUL-terminated character strings. */ #define bits(c) (0x80 | ((c) & 0x3F)) #define put(c) *strptr++ = (c); #define putbits(c) put(bits(c)) #define finish() *strptr = '\0' static char *sputu8(xds_uint32_t c, char *strptr) { if (strptr == NULL) return NULL; if (c < 0x80) { put(c); finish(); } else if (c < 0x800) { put(0xC0 | (c >> 6)); putbits(c); finish(); } else if (c < 0x10000) { put(0xE0 | (c >> 12)); putbits(c >> 6); putbits(c); finish(); } else if (c < 0x200000) { put(0xF0 | (c >> 18)); putbits(c >> 12); putbits(c >> 6); putbits(c); finish(); } else if (c < 0x400000) { put(0xF8 | (c >> 24)); putbits(c >> 18); putbits(c >> 12); putbits(c >> 6); putbits(c); finish(); } else if (c < 0x80000000) { put(0xFC | (c >> 30)); putbits(c >> 24); putbits(c >> 18); putbits(c >> 12); putbits(c >> 6); putbits(c); finish(); } else finish(); /* Not a valid Unicode "character" */ return strptr; } static const char TAG_OPEN[] = ""; static const char TAG_CLOSE[] = ""; static const size_t TAG_OPEN_LEN = sizeof (TAG_OPEN) - 1; static const size_t TAG_CLOSE_LEN = sizeof (TAG_CLOSE) - 1; int xml_encode_string(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { char *src; size_t src_len; char *dst; size_t dst_size; char *tmp; /* Setup the engine. We need at least space for our tags; how long the actual content is going to be will be seen soon. */ xds_init_encoding_engine(TAG_OPEN_LEN + TAG_CLOSE_LEN); /* Get the data from the stack. */ src = va_arg(*args, char *); xds_check_parameter(src != NULL); src_len = strlen(src); /* Set up the target buffer. */ dst = buffer; dst_size = buffer_size; /* Write the opening tag. */ memmove(dst, TAG_OPEN, TAG_OPEN_LEN); dst += TAG_OPEN_LEN; dst_size -= TAG_OPEN_LEN; /* Format the data into the buffer. */ while (src_len > 0 && dst_size > 0) { if (*((xds_uint8_t *) src) >= 0x80) { /* UTF-8ify it. */ if (dst_size >= 7) { tmp = sputu8((xds_uint32_t) * ((xds_uint8_t *) src), dst); src++; src_len--; dst_size -= tmp - dst; dst = tmp; } else dst_size = 0; } else if (*src == '<') { /* Turn into "<". */ if (dst_size >= 4) { *dst++ = '&'; dst_size--; *dst++ = 'l'; dst_size--; *dst++ = 't'; dst_size--; *dst++ = ';'; dst_size--; src++; src_len--; } else dst_size = 0; } else if (*src == '&') { /* Turn into "&". */ if (dst_size >= 5) { *dst++ = '&'; dst_size--; *dst++ = 'a'; dst_size--; *dst++ = 'm'; dst_size--; *dst++ = 'p'; dst_size--; *dst++ = ';'; dst_size--; src++; src_len--; } else dst_size = 0; } else if (*src == '>') { /* Turn into ">". */ if (dst_size >= 4) { *dst++ = '&'; dst_size--; *dst++ = 'g'; dst_size--; *dst++ = 't'; dst_size--; *dst++ = ';'; dst_size--; src++; src_len--; } else dst_size = 0; } else { /* No special character; just copy it. */ *dst++ = *src++; src_len--; dst_size--; } } if (src_len > 0) { /* Target buffer was too small. */ *used_buffer_size = buffer_size + 1; return XDS_ERR_OVERFLOW; } /* Write the closing tag. */ memmove(dst, TAG_CLOSE, TAG_CLOSE_LEN); dst += TAG_CLOSE_LEN; dst_size -= TAG_CLOSE_LEN; *used_buffer_size = dst - (char *)buffer; return XDS_OK; } #define INVALID \ 0x80000000 #define get(c) \ c = *strptr++; \ if (chars) \ (*chars)++; \ if ((c) == 0) \ return (unsigned int)EOF static unsigned int sgetu8(unsigned char *strptr, int *chars) { unsigned int c; int i, iterations; unsigned char ch; if (chars) *chars = 0; if (strptr == NULL) return (unsigned int)EOF; get(c); if ((c & 0xFE) == 0xFC) { c &= 0x01; iterations = 5; } else if ((c & 0xFC) == 0xF8) { c &= 0x03; iterations = 4; } else if ((c & 0xF8) == 0xF0) { c &= 0x07; iterations = 3; } else if ((c & 0xF0) == 0xE0) { c &= 0x0F; iterations = 2; } else if ((c & 0xE0) == 0xC0) { c &= 0x1F; iterations = 1; } else if ((c & 0x80) == 0x80) return INVALID; else return c; for (i = 0; i < iterations; i++) { get(ch); if ((ch & 0xC0) != 0x80) return INVALID; c <<= 6; c |= ch & 0x3F; } return c; } int xml_decode_string(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { char **target_buffer; char *src; size_t src_len; char *dst; int utf8_len; unsigned int rc; /* Setup the engine. We need at least space for our tags; how long the actual content is going to be will be seen soon. */ xds_init_encoding_engine(TAG_OPEN_LEN + TAG_CLOSE_LEN); /* Is the opening tag there? */ if (strncasecmp(buffer, TAG_OPEN, TAG_OPEN_LEN) != 0) return XDS_ERR_TYPE_MISMATCH; /* Determine the length of the encoded data. */ src = (char *)buffer + TAG_OPEN_LEN; for (src_len = 0; src[src_len] != '<'; ++src_len) if (src[src_len] == '\0') return XDS_ERR_TYPE_MISMATCH; /* Check the closing tag. */ if (strncasecmp(src + src_len, TAG_CLOSE, TAG_CLOSE_LEN) != 0) return XDS_ERR_TYPE_MISMATCH; *used_buffer_size = TAG_OPEN_LEN + src_len + TAG_CLOSE_LEN; /* Allocate target buffer. */ target_buffer = va_arg(*args, char **); xds_check_parameter(target_buffer != NULL); *target_buffer = dst = malloc(src_len + 1); if (dst == NULL) return XDS_ERR_NO_MEM; /* Decode the data into the target buffer. */ while (src_len > 0) { if (*src == '&') { if (src_len >= 4 && strncmp(src, "<", 4) == 0) { *dst++ = '<'; src += 4; src_len -= 4; } else if (src_len >= 4 && strncmp(src, ">", 4) == 0) { *dst++ = '>'; src += 4; src_len -= 4; } else if (src_len >= 5 && strncmp(src, "&", 5) == 0) { *dst++ = '&'; src += 5; src_len -= 5; } else { free(dst); return XDS_ERR_TYPE_MISMATCH; } } else if (*((xds_uint8_t *) src) >= 0x80) { rc = sgetu8((xds_uint8_t *)src, &utf8_len); if (rc == (unsigned int)EOF) return XDS_ERR_UNDERFLOW; else if (rc == INVALID || rc > 255) return XDS_ERR_TYPE_MISMATCH; *dst++ = (xds_uint8_t)rc; src += utf8_len; src_len -= utf8_len; } else { *dst++ = *src++; src_len--; } } *dst = '\0'; return XDS_OK; } /* * Encode/decode octet streams. */ static const char xds_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char xds_pad64 = '='; static int base64_encode(char *dst, size_t dstlen, unsigned char const *src, size_t srclen) { size_t dstpos; unsigned char input[3]; unsigned char output[4]; int ocnt; size_t i; if (srclen == 0) return 0; if (dst == NULL) { /* just calculate required length of dst */ dstlen = (((srclen + 2) / 3) * 4); return dstlen; } /* bulk encoding */ dstpos = 0; ocnt = 0; while (srclen >= 3) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclen -= 3; output[0] = ( input[0] >> 2); output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = ( input[2] & 0x3f); if (dstpos + 4 > dstlen) return -1; dst[dstpos++] = xds_base64[output[0]]; dst[dstpos++] = xds_base64[output[1]]; dst[dstpos++] = xds_base64[output[2]]; dst[dstpos++] = xds_base64[output[3]]; } /* now worry about padding with remaining 1 or 2 bytes */ if (srclen != 0) { input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclen; i++) input[i] = *src++; output[0] = ( input[0] >> 2); output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); if (dstpos + 4 > dstlen) return -1; dst[dstpos++] = xds_base64[output[0]]; dst[dstpos++] = xds_base64[output[1]]; if (srclen == 1) dst[dstpos++] = xds_pad64; else dst[dstpos++] = xds_base64[output[2]]; dst[dstpos++] = xds_pad64; } if (dstpos >= dstlen) return -1; dst[dstpos] = '\0'; return dstpos; } int xml_encode_octetstream(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { xds_uint8_t *src; size_t src_len; /* We need at least 27 byte for the starting and ending tag. */ xds_init_encoding_engine(13 + 14); /* Get parameters from stack. */ src = (xds_uint8_t *)va_arg(*args, void *); xds_check_parameter(src != NULL); src_len = va_arg(*args, size_t); /* Calculate how many bytes we'll need in buffer and make sure we have them. */ *used_buffer_size = base64_encode(NULL, 0, src, src_len); if (*used_buffer_size == (size_t) - 1) return XDS_ERR_UNKNOWN; else *used_buffer_size += 13 + 14; if (buffer_size < *used_buffer_size) return XDS_ERR_OVERFLOW; /* Format the data into the buffer. */ memmove(buffer, "", 13); if (base64_encode((char *)buffer + 13, buffer_size - 13, src, src_len) < 0) return XDS_ERR_UNKNOWN; memmove((char *)buffer + *used_buffer_size - 14, "", 14); /* Done. */ return XDS_OK; } static int base64_decode(unsigned char *dst, size_t dstlen, char const *src, size_t srclen) { int dstidx, state, ch = 0; unsigned char res; char *pos; if (srclen == 0) return 0; state = 0; dstidx = 0; res = 0; while (srclen-- > 0) { ch = *src++; if (isascii(ch) && isspace(ch)) /* Skip whitespace anywhere */ continue; if (ch == xds_pad64) break; pos = strchr(xds_base64, ch); if (pos == 0) /* A non-base64 character */ return -1; switch (state) { case 0: if (dst != NULL) { if ((size_t) dstidx >= dstlen) return -1; dst[dstidx] = ((pos - xds_base64) << 2); } state = 1; break; case 1: if (dst != NULL) { if ((size_t) dstidx >= dstlen) return -1; dst[dstidx] |= ((pos - xds_base64) >> 4); res = (((pos - xds_base64) & 0x0f) << 4); } dstidx++; state = 2; break; case 2: if (dst != NULL) { if ((size_t) dstidx >= dstlen) return -1; dst[dstidx] = res | ((pos - xds_base64) >> 2); res = ((pos - xds_base64) & 0x03) << 6; } dstidx++; state = 3; break; case 3: if (dst != NULL) { if ((size_t) dstidx >= dstlen) return -1; dst[dstidx] = res | (pos - xds_base64); } dstidx++; state = 0; break; default: break; } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == xds_pad64) { /* We got a pad char. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return -1; case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ while (srclen > 0) { ch = *src++; --srclen; if (!(isascii(ch) && isspace(ch))) break; } /* Make sure there is another trailing = sign. */ if (ch != xds_pad64) return -1; /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ while (srclen > 0) { ch = *src++; --srclen; if (!(isascii(ch) && isspace(ch))) return -1; } /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (dst != NULL && res != 0) return -1; default: break; } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return -1; } return dstidx; } int xml_decode_octetstream(xds_t *xds, void *engine_context, void *buffer, size_t buffer_size, size_t *used_buffer_size, va_list *args) { char *p; size_t p_len; xds_uint8_t **data; size_t *data_len; /* We need at least 27 byte for the starting and ending tag. */ xds_init_encoding_engine(13 + 14); /* Get parameters from stack. */ data = va_arg(*args, xds_uint8_t **); xds_check_parameter(data != NULL); data_len = va_arg(*args, size_t *); /* Check for the opening tag. */ if (memcmp("", buffer, 13) != 0) return XDS_ERR_TYPE_MISMATCH; /* Find the end of the data and calculate the length of the base64-encoded stuff. */ p = (char *)buffer + 13; while (p < ((char *)buffer + buffer_size) && *p != '<') ++p; if (p == ((char *)buffer + buffer_size)) return XDS_ERR_TYPE_MISMATCH; else { p_len = p - ((char *)buffer + 13); p = (char *)buffer + 13; } /* Now find out how long the decoded data is going to be, allocate a buffer for it, and decode away. */ *data_len = base64_decode(NULL, 0, p, p_len); if (*data_len == (size_t) - 1) return XDS_ERR_UNKNOWN; *data = malloc(*data_len); if (*data == NULL) return XDS_ERR_NO_MEM; base64_decode(*data, *data_len, p, p_len); /* Check that we have a closing tag. */ if (memcmp(p + p_len, "", 14) != 0) { free(*data); return XDS_ERR_TYPE_MISMATCH; } *used_buffer_size = 13 + p_len + 14; return XDS_OK; } @ 1.13 log @Bumped year in copyright messages for year 2004. @ text @d3 3 a5 3 ** Copyright (c) 2001-2004 Ralf S. Engelschall ** Copyright (c) 2001-2004 The OSSP Project ** Copyright (c) 2001-2004 Cable & Wireless @ 1.12 log @Fixed a few size_t/int conflicts and uninitialized value warnings. @ text @d3 3 a5 3 ** Copyright (c) 2001-2003 Ralf S. Engelschall ** Copyright (c) 2001-2003 The OSSP Project ** Copyright (c) 2001-2003 Cable & Wireless Germany @ 1.11 log @upgrade to standard OSSP copyright and bump year to 2003 @ text @d437 2 a438 1 { d441 1 a441 1 va_arg(*args, float*), used_buffer_size) != 1) d443 2 a444 1 else d447 1 d470 1 d473 1 a473 1 va_arg(*args, double*), used_buffer_size) != 1) d475 2 a476 1 else d478 1 @ 1.10 log @update texts @ text @d3 3 a5 2 ** Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.9 log @bump copyright year @ text @d2 1 a2 1 ** XDS - OSSP Extensible Data Serialization Library d6 2 a7 2 ** This file is part of OSSP XDS, an extensible data serialization ** library which can be found at http://www.ossp.org/pkg/xds/. d42 1 a42 1 "\n" @ 1.8 log @Implemented xml_encode_double(), xml_decode_double(), xml_encode_float(), and xml_decode_float(). @ text @d3 2 a4 2 ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.7 log @Remove trailing whitespaces on all non-generated files. @ text @d417 29 d453 7 a459 2 /* XXX */ return -1; d466 6 a471 2 /* XXX */ return -1; @ 1.6 log @Hhmm... who has introduced ossp.com?! Our project's domain is ossp.org, of course. @ text @d45 1 a45 1 static const char xds_xml_end_text[] = d62 1 a62 1 if (strncasecmp(buffer, xds_xml_begin_text, d82 1 a82 1 if (strncasecmp(buffer, xds_xml_end_text, d530 1 a530 1 if (*((xds_uint8_t *) src) >= 0x80) { d542 1 a542 1 else if (*src == '<') { d595 1 a595 1 else { d763 1 a763 1 static int base64_encode(char *dst, size_t dstlen, d866 1 a866 1 static int base64_decode(unsigned char *dst, size_t dstlen, d930 1 a930 1 /* d952 1 a952 1 /* d962 1 a962 1 /* d975 1 a975 1 /* @ 1.5 log @Group functions with leading summary comment @ text @d7 1 a7 1 ** library which can be found at http://www.ossp.com/pkg/xds/. @ 1.4 log @Final adjustments to coding style in order to make OSSP XDS look equal in style to all other OSSP parts. This should remove most of the strangeness GNU indent usually introduces. @ text @d36 4 d88 4 d178 4 d252 4 d342 4 d416 4 d436 4 d754 4 @ 1.3 log @Use the license consistently. @ text @d44 1 a44 1 int xml_encode_begin(xds_t * xds, void *engine_context, d46 1 a46 1 size_t * used_buffer_size, va_list * args) d53 1 a53 1 int xml_decode_begin(xds_t * xds, void *engine_context, d55 1 a55 1 size_t * used_buffer_size, va_list * args) d58 2 a59 2 if (strncasecmp(buffer, xds_xml_begin_text, strlen(xds_xml_begin_text)) != 0) d64 1 a64 1 int xml_encode_end(xds_t * xds, void *engine_context, d66 1 a66 1 size_t * used_buffer_size, va_list * args) d73 1 a73 1 int xml_decode_end(xds_t * xds, void *engine_context, d75 1 a75 1 size_t * used_buffer_size, va_list * args) d78 2 a79 1 if (strncasecmp(buffer, xds_xml_end_text, strlen(xds_xml_end_text)) != 0) d84 1 a84 1 int xml_encode_int32(xds_t * xds, void *engine_context, d86 1 a86 1 size_t * used_buffer_size, va_list * args) d97 1 a97 2 * of the formatted result. */ d110 1 a110 2 } while (value != 0); d115 1 a115 2 * it into the buffer. */ d120 1 a120 1 for (j = i; j > 0;) { a121 1 } d127 1 a127 1 int xml_decode_int32(xds_t * xds, void *engine_context, d129 1 a129 1 size_t * used_buffer_size, va_list * args) a137 1 a141 1 d147 1 a147 1 ++p; a160 1 d170 1 a170 1 int xml_encode_uint32(xds_t * xds, void *engine_context, d172 1 a172 1 size_t * used_buffer_size, va_list * args) a181 1 d188 1 a188 2 } while (value != 0); a190 1 a193 1 d197 1 a197 1 for (j = i; j > 0;) { a198 1 } d204 1 a204 1 int xml_decode_uint32(xds_t * xds, void *engine_context, d206 1 a206 1 size_t * used_buffer_size, va_list * args) a213 1 a217 1 a228 1 d240 1 a240 1 int xml_encode_int64(xds_t * xds, void *engine_context, d242 1 a242 1 size_t * used_buffer_size, va_list * args) a252 1 d265 1 a265 2 } while (value != 0); a269 1 a272 1 d276 1 a276 1 for (j = i; j > 0;) { a277 1 } d283 1 a283 1 int xml_decode_int64(xds_t * xds, void *engine_context, d285 1 a285 1 size_t * used_buffer_size, va_list * args) a293 1 a297 1 d303 1 a303 1 ++p; a316 1 d326 1 a326 1 int xml_encode_uint64(xds_t * xds, void *engine_context, d328 1 a328 1 size_t * used_buffer_size, va_list * args) a337 1 d344 1 a344 2 } while (value != 0); a346 1 a349 1 d353 1 a353 1 for (j = i; j > 0;) { a354 1 } d360 1 a360 1 int xml_decode_uint64(xds_t * xds, void *engine_context, d362 1 a362 1 size_t * used_buffer_size, va_list * args) a369 1 a373 1 a384 1 d396 1 a396 1 int xml_encode_double(xds_t * xds, void *engine_context, d398 1 a398 1 size_t * used_buffer_size, va_list * args) d400 1 d404 1 a404 1 int xml_decode_double(xds_t * xds, void *engine_context, d406 1 a406 1 size_t * used_buffer_size, va_list * args) d408 1 d412 2 a413 2 #define bits(c) (0x80 | ((c) & 0x3F)) #define put(c) *strptr++ = (c); d462 1 a462 1 finish(); /* Not a valid Unicode "character" */ d467 3 a469 3 static const char TAG_OPEN[] = ""; static const char TAG_CLOSE[] = ""; static const size_t TAG_OPEN_LEN = sizeof (TAG_OPEN) - 1; d472 1 a472 1 int xml_encode_string(xds_t * xds, void *engine_context, d474 1 a474 1 size_t * used_buffer_size, va_list * args) d483 1 a483 2 * actual content is going to be will be seen soon. */ a486 1 a491 1 a495 1 a500 1 d502 2 a503 1 if (*((xds_uint8_t *) src) >= 0x80) { /* UTF-8ify it. */ d506 2 a507 2 ++src; --src_len; d514 2 a515 1 else if (*src == '<') { /* Turn into "<". */ d518 1 a518 1 --dst_size; d520 1 a520 1 --dst_size; d522 1 a522 1 --dst_size; d524 3 a526 3 --dst_size; ++src; --src_len; d531 2 a532 1 else if (*src == '&') { /* Turn into "&". */ d535 1 a535 1 --dst_size; d537 1 a537 1 --dst_size; d539 1 a539 1 --dst_size; d541 1 a541 1 --dst_size; d543 3 a545 3 --dst_size; ++src; --src_len; d550 2 a551 1 else if (*src == '>') { /* Turn into ">". */ d554 1 a554 1 --dst_size; d556 1 a556 1 --dst_size; d558 1 a558 1 --dst_size; d560 3 a562 3 --dst_size; ++src; --src_len; d567 2 a568 2 else { /* No special character; just copy it. */ d570 2 a571 2 --src_len; --dst_size; d574 2 a575 1 if (src_len > 0) { /* Target buffer was too small. */ a580 1 a584 2 /* Done. */ d589 8 a596 5 #define INVALID 0x80000000 #define get(c) c = *strptr++; \ if (chars) (*chars)++; \ if ((c) == 0) return (unsigned int)EOF a610 1 d647 1 a647 1 int xml_decode_string(xds_t * xds, void *engine_context, d649 1 a649 1 size_t * used_buffer_size, va_list * args) d659 1 a659 2 * actual content is going to be will be seen soon. */ a662 1 a666 1 a672 1 a677 1 a684 1 d708 1 a708 1 rc = sgetu8((xds_uint8_t *) src, &utf8_len); d713 1 a713 1 *dst++ = (xds_uint8_t) rc; d719 1 a719 1 --src_len; a723 2 /* Done. */ d731 2 a732 2 static int base64_encode(char *dst, size_t dstlen, unsigned char const *src, size_t srclen) d757 1 a757 1 output[0] = (input[0] >> 2); d760 1 a760 1 output[3] = (input[2] & 0x3f); d776 1 a776 1 output[0] = (input[0] >> 2); d798 1 a798 1 int xml_encode_octetstream(xds_t * xds, void *engine_context, d800 1 a800 1 size_t * used_buffer_size, va_list * args) a805 1 d809 1 a809 2 src = (xds_uint8_t *) va_arg(*args, void *); d814 1 a814 2 * them. */ a823 1 d825 1 a825 2 if (base64_encode((char *)buffer + 13, buffer_size - 13, src, src_len) < 0) d834 2 a835 2 static int base64_decode(unsigned char *dst, size_t dstlen, char const *src, size_t srclen) d902 1 a902 2 if (ch == xds_pad64) { /* We got a pad char. */ d954 1 a954 1 int xml_decode_octetstream(xds_t * xds, void *engine_context, d956 1 a956 1 size_t * used_buffer_size, va_list * args) a963 1 a966 1 a971 1 d976 1 a976 2 * base64-encoded stuff. */ d988 1 a988 2 * buffer for it, and decode away. */ a997 1 a1002 2 /* Done. */ d1006 1 @ 1.2 log @Do not export internal things. @ text @d1 28 a28 23 /* * XDS - OSSP Extensible Data Serialization Library Copyright (c) 2001 The * OSSP Project (http://www.ossp.org/) Copyright (c) 2001 Cable & Wireless * Deutschland (http://www.cw.com/de/) * * This file is part of OSSP XDS, an extensible data serialization library * which can be found at http://www.ossp.com/pkg/xds/. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR 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. */ d33 1 @ 1.1 log @First cut of the ruthless style adjustments to OSSP XDS: o adjust source tree to follow OSSP source tree style by heavily combining sources into smaller sets (needs more work when still missing parts are added later) o automatic re-indentation of sources with GNU indent (still needs manual review and adjustments; will follow) These two heavy steps were mostly done automatically with the help of two helper scripts written in Perl. So expect more manual adjustments to follow... @ text @d30 1 a30 1 const char xds_xml_begin_text[] = d35 3 a57 2 const char xds_xml_end_text[] = "\n"; d758 1 a758 1 const char xds_base64[] = d760 1 a760 1 const char xds_pad64 = '='; @