summaryrefslogtreecommitdiff
path: root/libedsio/base64.c
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-02-22 07:24:03 -0800
committerAnas Nashif <anas.nashif@intel.com>2013-02-22 07:24:03 -0800
commit2cdd5bf0e73eff343d4ca085b315e78982e76202 (patch)
treee9082ffa48b4651e998fd9caa1dab827a9e6b7ae /libedsio/base64.c
downloadxdelta1-2cdd5bf0e73eff343d4ca085b315e78982e76202.tar.gz
xdelta1-2cdd5bf0e73eff343d4ca085b315e78982e76202.tar.bz2
xdelta1-2cdd5bf0e73eff343d4ca085b315e78982e76202.zip
Imported Upstream version 1.1.4upstream/1.1.4upstream
Diffstat (limited to 'libedsio/base64.c')
-rwxr-xr-xlibedsio/base64.c525
1 files changed, 525 insertions, 0 deletions
diff --git a/libedsio/base64.c b/libedsio/base64.c
new file mode 100755
index 0000000..c37ddae
--- /dev/null
+++ b/libedsio/base64.c
@@ -0,0 +1,525 @@
+/* -*-Mode: C;-*-
+ * $Id: base64.c 1.1 Sun, 28 Jan 2007 10:02:26 -0800 jmacd $
+ *
+ * Copyright (C) 1998, 1999, Josh MacDonald.
+ * All Rights Reserved.
+ *
+ * Author: Josh MacDonald <jmacd@CS.Berkeley.EDU>
+ */
+
+#include "edsio.h"
+
+/* BASE64 Encoding
+ */
+
+static const unsigned char base64_table[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
+ 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
+ '3', '4', '5', '6', '7', '8', '9', '+', '/'
+};
+
+static gint16 base64_inverse_table[128];
+
+static void
+init_inverse_table (void)
+{
+ static int i = 0;
+ static int j = 0;
+
+ for (; j < 128; j += 1)
+ base64_inverse_table[j] = -1;
+
+ for (; i < 64; i += 1)
+ base64_inverse_table[base64_table[i]] = i;
+
+ base64_inverse_table['='] = 0;
+}
+
+GByteArray*
+edsio_base64_encode_region (const guint8* data, guint len)
+{
+ GByteArray* out = g_byte_array_new ();
+ guint real_len;
+
+ g_byte_array_set_size (out, (len+2)*4/3);
+
+ real_len = out->len;
+
+ if (! edsio_base64_encode_region_into (data, len, out->data, &real_len))
+ {
+ g_byte_array_free (out, TRUE);
+ return NULL;
+ }
+
+ g_byte_array_set_size (out, real_len);
+
+ return out;
+}
+
+gboolean
+edsio_base64_encode_region_into (const guint8* data, guint len, guint8* out, guint *out_len)
+{
+ gint i;
+ guint32 word = 0, count = 0;
+
+ if ((*out_len) < (len + 2) * 4/3)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ *out_len = 0;
+
+ for (i = 0; i < len; i += 1)
+ {
+ word |= data[i] << (8*(2-(count++)));
+
+ if (count == 3)
+ {
+ out[(*out_len)++] = base64_table[(word>>18) & 0x3f];
+ out[(*out_len)++] = base64_table[(word>>12) & 0x3f];
+ out[(*out_len)++] = base64_table[(word>> 6) & 0x3f];
+ out[(*out_len)++] = base64_table[(word ) & 0x3f];
+
+ count = 0;
+ word = 0;
+ }
+ }
+
+ if (count > 0)
+ {
+ out[(*out_len)++] = base64_table[(word>>18) & 0x3f];
+ out[(*out_len)++] = base64_table[(word>>12) & 0x3f];
+ out[(*out_len)++] = (count > 1) ? base64_table[(word>>6) & 0x3f] : '=';
+ out[(*out_len)++] = '=';
+ }
+
+ return TRUE;
+}
+
+GByteArray*
+edsio_base64_decode_region (const guint8* data, guint data_len)
+{
+ GByteArray* it = g_byte_array_new ();
+ guint real_len;
+
+ g_byte_array_set_size (it, data_len*3/4);
+
+ real_len = it->len;
+
+ if (! edsio_base64_decode_region_into (data, data_len, it->data, &real_len))
+ {
+ g_byte_array_free (it, TRUE);
+ return NULL;
+ }
+
+ g_byte_array_set_size (it, real_len);
+
+ return it;
+}
+
+gboolean
+edsio_base64_decode_region_into (const guint8* data, guint len, guint8* out, guint *out_len)
+{
+ guint32 pos = 0;
+ gboolean found_end = FALSE;
+ gint found_end_at = 0;
+
+ init_inverse_table ();
+
+ if ((*out_len) < (len*3/4))
+ {
+ edsio_generate_void_event (EC_EdsioOutputBufferShort);
+ return FALSE;
+ }
+
+ (*out_len) = 0;
+
+ while (pos < len)
+ {
+ gint i, x;
+ gint word = 0, junk = 0;
+
+ if (len - pos < 4)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ for (i = 0; i < 4; i += 1)
+ {
+ x = data[pos++];
+
+ if (x > 127 || base64_inverse_table[x] < 0)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ if (x == '=')
+ {
+ if (! found_end)
+ found_end_at = i;
+
+ found_end = TRUE;
+ }
+ else
+ {
+ if (found_end)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ word |= base64_inverse_table[x] << (6*(3-i));
+ }
+ }
+
+ if (found_end)
+ {
+ if (found_end_at < 2)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ if (found_end_at == 2)
+ junk = 2;
+ else if (found_end_at == 3)
+ junk = 1;
+ }
+ else
+ junk = 0;
+
+ out[(*out_len)++] = (word >> 16) & 0xff;
+
+ if (junk < 2)
+ out[(*out_len)++] = (word >> 8) & 0xff;
+
+ if (junk < 1)
+ out[(*out_len)++] = (word >> 0) & 0xff;
+ }
+
+ return TRUE;
+}
+
+/* Base64 sink
+ */
+typedef struct _Base64Sink Base64Sink;
+
+static gboolean base64_sink_close (SerialSink* sink);
+static gboolean base64_sink_write (SerialSink* sink, const guint8 *ptr, guint32 len);
+static void base64_sink_free (SerialSink* sink);
+static gboolean base64_sink_quantum (SerialSink* sink);
+
+struct _Base64Sink
+{
+ SerialSink sink;
+
+ SerialSink* out;
+
+ guint32 word;
+ guint32 count;
+};
+
+SerialSink*
+serializeio_base64_sink (SerialSink* out)
+{
+ Base64Sink* it = g_new0 (Base64Sink, 1);
+ SerialSink* sink = (SerialSink*) it;
+
+ serializeio_sink_init (sink,
+ NULL,
+ base64_sink_close,
+ base64_sink_write,
+ base64_sink_free,
+ base64_sink_quantum);
+
+ it->out = out;
+
+ return sink;
+}
+
+gboolean
+base64_sink_write (SerialSink* fsink, const guint8 *ptr, guint32 len)
+{
+ guint32 i;
+
+ Base64Sink* sink = (Base64Sink*) fsink;
+
+ for (i = 0; i < len; )
+ {
+ if (sink->count == 3)
+ {
+ guint8 out[4];
+
+ out[0] = base64_table[(sink->word>>18) & 0x3f];
+ out[1] = base64_table[(sink->word>>12) & 0x3f];
+ out[2] = base64_table[(sink->word>> 6) & 0x3f];
+ out[3] = base64_table[(sink->word ) & 0x3f];
+
+#if 0
+ g_print ("%02x %02x %02x -> %c%c%c%c (3)\n",
+ (sink->word>>16) & 0xff,
+ (sink->word>>8) & 0xff,
+ (sink->word>>0) & 0xff,
+ out[0],
+ out[1],
+ out[2],
+ out[3]);
+#endif
+
+ if (! sink->out->sink_write (sink->out, out, 4))
+ return FALSE;
+
+ sink->count = 0;
+ sink->word = 0;
+ }
+
+ while (sink->count < 3 && i < len)
+ sink->word |= ptr[i++] << (8*(2-(sink->count++)));
+ }
+
+ return TRUE;
+}
+
+gboolean
+base64_sink_close (SerialSink* fsink)
+{
+ Base64Sink* sink = (Base64Sink*) fsink;
+
+ if (sink->count == 3)
+ {
+ guint8 out[4];
+
+ out[0] = base64_table[(sink->word>>18) & 0x3f];
+ out[1] = base64_table[(sink->word>>12) & 0x3f];
+ out[2] = base64_table[(sink->word>> 6) & 0x3f];
+ out[3] = base64_table[(sink->word ) & 0x3f];
+
+#if 0
+ g_print ("%02x %02x %02x -> %c%c%c%c (3)\n",
+ (sink->word>>16) & 0xff,
+ (sink->word>>8) & 0xff,
+ (sink->word>>0) & 0xff,
+ out[0],
+ out[1],
+ out[2],
+ out[3]);
+#endif
+
+ if (! sink->out->sink_write (sink->out, out, 4))
+ return FALSE;
+
+ sink->count = 0;
+ sink->word = 0;
+ }
+
+ if (sink->count > 0)
+ {
+ guint8 out[4];
+
+ out[0] = base64_table[(sink->word>>18) & 0x3f];
+ out[1] = base64_table[(sink->word>>12) & 0x3f];
+ out[2] = (sink->count > 1) ? base64_table[(sink->word>>6) & 0x3f] : '=';
+ out[3] = '=';
+
+#if 0
+ g_print ("%02x %02x %02x -> %c%c%c%c (%d)\n",
+ (sink->word>>16) & 0xff,
+ (sink->word>>8) & 0xff,
+ (sink->word>>0) & 0xff,
+ out[0],
+ out[1],
+ out[2],
+ out[3],
+ sink->count);
+#endif
+
+ if (! sink->out->sink_write (sink->out, out, 4))
+ return FALSE;
+
+ sink->count = 0;
+ sink->word = 0;
+ }
+
+ return sink->out->sink_close (sink->out);
+}
+
+
+void
+base64_sink_free (SerialSink* fsink)
+{
+ Base64Sink* sink = (Base64Sink*) fsink;
+
+ sink->out->sink_free (sink->out);
+
+ g_free (sink);
+}
+
+gboolean
+base64_sink_quantum (SerialSink* fsink)
+{
+ Base64Sink* sink = (Base64Sink*) fsink;
+
+ if (sink->out->sink_quantum)
+ return sink->out->sink_quantum (sink->out);
+
+ return TRUE;
+}
+
+/* Base64 source
+ */
+
+typedef struct _Base64Source Base64Source;
+
+struct _Base64Source {
+ SerialSource source;
+
+ SerialSource *in;
+
+ guint32 avail;
+ guint32 count;
+ gboolean found_end;
+ gint found_end_at;
+ guint8 buf[3];
+};
+
+static gboolean base64_source_close (SerialSource* source);
+static gboolean base64_source_read (SerialSource* source, guint8 *ptr, guint32 len);
+static void base64_source_free (SerialSource* source);
+
+SerialSource*
+serializeio_base64_source (SerialSource* in0)
+{
+ Base64Source* it = g_new0 (Base64Source, 1);
+ SerialSource* source = (SerialSource*) it;
+
+ serializeio_source_init (source,
+ NULL,
+ base64_source_close,
+ base64_source_read,
+ base64_source_free,
+ NULL,
+ NULL);
+
+ it->in = in0;
+
+ return source;
+}
+
+gboolean
+base64_source_close (SerialSource* fsource)
+{
+ Base64Source* source = (Base64Source*) fsource;
+
+ if (! source->in->source_close (source->in))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+base64_source_read (SerialSource* fsource, guint8 *ptr, guint32 len)
+{
+ guint32 pos;
+ Base64Source* source = (Base64Source*) fsource;
+
+ init_inverse_table ();
+
+ for (pos = 0; pos < len; )
+ {
+ if (source->count == 0)
+ {
+ guint8 buf[4];
+ guint32 i, word = 0, junk;
+
+ if (source->found_end)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ if (! source->in->source_read (source->in, buf, 4))
+ return FALSE;
+
+ for (i = 0; i < 4; i += 1)
+ {
+ gint x = buf[i];
+
+ if (x > 127 || base64_inverse_table[x] < 0)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ if (x == '=')
+ {
+ if (! source->found_end)
+ source->found_end_at = i;
+
+ source->found_end = TRUE;
+ }
+ else
+ {
+ if (source->found_end)
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+
+ word |= base64_inverse_table[x] << (6*(3-i));
+ }
+ }
+
+ if (source->found_end)
+ {
+ if (source->found_end_at == 2)
+ junk = 2;
+ else if (source->found_end_at == 3)
+ junk = 1;
+ else
+ {
+ edsio_generate_void_event (EC_EdsioInvalidBase64Encoding);
+ return FALSE;
+ }
+ }
+ else
+ junk = 0;
+
+ source->avail = source->count = 3 - junk;
+
+ source->buf[0] = (word >> 16) & 0xff;
+ source->buf[1] = (word >> 8) & 0xff;
+ source->buf[2] = (word >> 0) & 0xff;
+
+#if 0
+ g_print ("%c%c%c%c -> %02x %02x %02x (%d)\n",
+ buf[0],
+ buf[1],
+ buf[2],
+ buf[3],
+ (word>>16) & 0xff,
+ (word>>8) & 0xff,
+ (word>>0) & 0xff,
+ 3-junk);
+#endif
+ }
+
+ ptr[pos++] = source->buf[source->avail-(source->count--)];
+ }
+
+ return TRUE;
+}
+
+void
+base64_source_free (SerialSource* fsource)
+{
+ Base64Source* source = (Base64Source*) fsource;
+
+ source->in->source_free (source->in);
+
+ g_free (source);
+}