OSSP CVS Repository

ossp - Check-in [4280]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 4280
Date: 2001-Aug-02 19:24:50 (local)
2001-Aug-02 17:24:50 (UTC)
User:simons
Branch:
Comment: Implemented XML engines for octet streams. The base64-encoding code still needs some work, though: The test with an empty string currently fails. Also we had to do some weird work-arounds in the decoding routine because base64_decode does not honor srclen.
Tickets:
Inspections:
Files:
ossp-pkg/xds/regression-tests/Makefile.in      1.12->removed
ossp-pkg/xds/regression-tests/xml-octetstream-empty.c      added-> 1.1
ossp-pkg/xds/regression-tests/xml-octetstream.c      added-> 1.1
ossp-pkg/xds/xml-decode-octetstream.c      added-> 1.1
ossp-pkg/xds/xml-encode-octetstream.c      added-> 1.1

ossp-pkg/xds/regression-tests/Makefile.in 1.12 -> 1.13

--- Makefile.in  2001/08/02 14:56:14     1.12
+++ Makefile.in  2001/08/02 17:24:50     1.13
@@ -13,7 +13,7 @@
                   xds-getbuffer.exe xds-decode.exe xds-setbuffer.exe xds-engine-restart.exe \
                   xdr-uint32.exe xdr-int32.exe xdr-octetstream.exe xdr-octetstream-empty.exe \
                   xdr-string.exe xdr-string-empty.exe xml-uint32.exe xml-int32.exe \
-                  xml-double.exe $(TESTS64)
+                  xml-double.exe xml-octetstream.exe xml-octetstream-empty.exe $(TESTS64)
 
 .SUFFIXES:
 .SUFFIXES:      .c .exe


ossp-pkg/xds/regression-tests/xml-octetstream-empty.c -> 1.1

*** /dev/null    Sat Nov 23 01:18:21 2024
--- -    Sat Nov 23 01:18:33 2024
***************
*** 0 ****
--- 1,109 ----
+ /*
+    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.
+ */
+ 
+ #include <unistd.h>
+ 
+ #include <stdio.h>
+ #include <string.h>
+ #include "../internal.h"
+ 
+ int main()
+     {
+     xds_t* xds;
+     char*  buffer;
+     size_t buffer_size;
+ 
+     char   msg[] = "";
+     char*  new_msg;
+     size_t new_msg_size;
+ 
+     /* Encode the string as octet stream. Then erase the buffer and
+        decode the string back, verifying that it hasn't changed. */
+ 
+     xds = xds_init(XDS_ENCODE);
+     if (xds == NULL)
+        {
+        printf("Failed to initialize XDS context.\n");
+        return 1;
+        }
+     if (xds_register(xds, "os", &xml_encode_octetstream, NULL) != XDS_OK)
+        {
+        printf("Failed to register my encoding engines.\n");
+        return 1;
+        }
+     if (xds_encode(xds, "os", msg, strlen(msg)) != XDS_OK)
+        {
+        printf("xds_encode() failed.\n");
+        return 1;
+        }
+     if (xds_getbuffer(xds, XDS_GIFT, (void**)&buffer, &buffer_size) != XDS_OK)
+        {
+        printf("xds_getbuffer() failed.\n");
+        return 1;
+        }
+     xds_destroy(xds);
+     write(1, buffer, buffer_size);
+     printf("\n");
+ 
+     xds = xds_init(XDS_DECODE);
+     if (xds == NULL)
+        {
+        printf("Failed to initialize XDS context.\n");
+        return 1;
+        }
+     if (xds_register(xds, "os", &xml_decode_octetstream, NULL) != XDS_OK)
+        {
+        printf("Failed to register my decoding engines.\n");
+        return 1;
+        }
+     if (xds_setbuffer(xds, XDS_GIFT, buffer, buffer_size) != XDS_OK)
+        {
+        printf("xds_setbuffer() failed.\n");
+        return 1;
+        }
+     if (xds_decode(xds, "os", &new_msg, &new_msg_size) != XDS_OK)
+        {
+        printf("xds_decode() failed.\n");
+        return 1;
+        }
+     if (new_msg_size != strlen(msg))
+        {
+        printf("The size of the decoded message is wrong.\n");
+        return 1;
+        }
+     if (memcmp(msg, new_msg, new_msg_size) != 0)
+        {
+        printf("The decoded octet stream is not correct.\n");
+        return 1;
+        }
+     xds_destroy(xds);
+     free(new_msg);
+ 
+     /* Everything went fine. */
+ 
+     return 0;
+     }


ossp-pkg/xds/regression-tests/xml-octetstream.c -> 1.1

*** /dev/null    Sat Nov 23 01:18:21 2024
--- -    Sat Nov 23 01:18:33 2024
***************
*** 0 ****
--- 1,109 ----
+ /*
+    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.
+ */
+ 
+ #include <unistd.h>
+ 
+ #include <stdio.h>
+ #include <string.h>
+ #include "../internal.h"
+ 
+ int main()
+     {
+     xds_t* xds;
+     char*  buffer;
+     size_t buffer_size;
+ 
+     char   msg[] = "Hello World";
+     char*  new_msg;
+     size_t new_msg_size;
+ 
+     /* Encode the string as octet stream. Then erase the buffer and
+        decode the string back, verifying that it hasn't changed. */
+ 
+     xds = xds_init(XDS_ENCODE);
+     if (xds == NULL)
+        {
+        printf("Failed to initialize XDS context.\n");
+        return 1;
+        }
+     if (xds_register(xds, "os", &xml_encode_octetstream, NULL) != XDS_OK)
+        {
+        printf("Failed to register my encoding engines.\n");
+        return 1;
+        }
+     if (xds_encode(xds, "os", msg, strlen(msg)) != XDS_OK)
+        {
+        printf("xds_encode() failed.\n");
+        return 1;
+        }
+     if (xds_getbuffer(xds, XDS_GIFT, (void**)&buffer, &buffer_size) != XDS_OK)
+        {
+        printf("xds_getbuffer() failed.\n");
+        return 1;
+        }
+     xds_destroy(xds);
+     write(1, buffer, buffer_size);
+     printf("\n");
+ 
+     xds = xds_init(XDS_DECODE);
+     if (xds == NULL)
+        {
+        printf("Failed to initialize XDS context.\n");
+        return 1;
+        }
+     if (xds_register(xds, "os", &xml_decode_octetstream, NULL) != XDS_OK)
+        {
+        printf("Failed to register my decoding engines.\n");
+        return 1;
+        }
+     if (xds_setbuffer(xds, XDS_GIFT, buffer, buffer_size) != XDS_OK)
+        {
+        printf("xds_setbuffer() failed.\n");
+        return 1;
+        }
+     if (xds_decode(xds, "os", &new_msg, &new_msg_size) != XDS_OK)
+        {
+        printf("xds_decode() failed.\n");
+        return 1;
+        }
+     if (new_msg_size != strlen(msg))
+        {
+        printf("The size of the decoded message is wrong.\n");
+        return 1;
+        }
+     if (memcmp(msg, new_msg, new_msg_size) != 0)
+        {
+        printf("The decoded octet stream is not correct.\n");
+        return 1;
+        }
+     xds_destroy(xds);
+     free(new_msg);
+ 
+     /* Everything went fine. */
+ 
+     return 0;
+     }


ossp-pkg/xds/xml-decode-octetstream.c -> 1.1

*** /dev/null    Sat Nov 23 01:18:21 2024
--- -    Sat Nov 23 01:18:33 2024
***************
*** 0 ****
--- 1,226 ----
+ /*
+    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.
+ */
+ 
+ #include <string.h>
+ #include <ctype.h>
+ #include "xds.h"
+ 
+ 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)
+         srclen = strlen(src);
+     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. */
+         ch = *src++;            /* Skip it, get next. */
+         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. */
+                 for (; ch != '\0'; ch = *src++)
+                     if (!(isascii(ch) && isspace(ch)))
+                         break;
+                 /* Make sure there is another trailing = sign. */
+                 if (ch != xds_pad64)
+                     return -1;
+                 ch = *src++;        /* Skip the = */
+                 /* FALLTHROUGH */
+             case 3:             /* Valid, means two bytes of info */
+                 /*
+                  * We know this char is an =.  Is there anything but
+                  * whitespace after it?
+                  */
+                 for (; ch != '\0'; ch = *src++)
+                     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("<octetstream>", 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 and
+        allocate a buffer for it. */
+ 
+     p[p_len] = '\0';
+     *data_len = base64_decode(NULL, 0, p, p_len);
+     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;
+ 
+     /* Decode the data. */
+ 
+     p[p_len] = '\0';
+     base64_decode(*data, *data_len, p, p_len);
+     p[p_len] = '<';
+ 
+     /* Check that we have a closing tag. */
+ 
+     if (memcmp(p + p_len, "</octetstream>", 14) != 0)
+        {
+        free(*data);
+        return XDS_ERR_TYPE_MISMATCH;
+        }
+ 
+     /* Done. */
+ 
+     *used_buffer_size = 13 + p_len + 14;
+     return XDS_OK;
+     }
+ 


ossp-pkg/xds/xml-encode-octetstream.c -> 1.1

*** /dev/null    Sat Nov 23 01:18:21 2024
--- -    Sat Nov 23 01:18:33 2024
***************
*** 0 ****
--- 1,142 ----
+ /*
+    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.
+ */
+ 
+ #include <string.h>
+ #include <ctype.h>
+ #include "xds.h"
+ 
+ const char xds_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ 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 -1;
+     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, "<octetstream>", 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, "</octetstream>", 14);
+ 
+     /* Done. */
+ 
+     return XDS_OK;
+     }

CVSTrac 2.0.1