/*
- * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>
+ * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <stdlib.h>
#include <string.h>
+#include "encoding.h"
#include "base32.h"
static const char cb32[] =
"abcdefghijklmnopqrstuvwxyz0123456789";
+static unsigned char rev32[128];
+static int reverse_init = 0;
+
+static struct encoder base32_encoder =
+{
+ "BASE32",
+ base32_encode,
+ base32_decode,
+ base32_handles_dots,
+ base32_handles_dots
+};
+
+struct encoder
+*get_base32_encoder()
+{
+ return &base32_encoder;
+}
+
+int
+base32_handles_dots()
+{
+ return 0;
+}
int
-base32_encode(char **buf, size_t *buflen, const void *data, size_t size)
+base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
{
size_t newsize;
- char *newbuf;
- char *s;
- char *p;
- char *q;
+ size_t maxsize;
+ unsigned char *s;
+ unsigned char *p;
+ unsigned char *q;
int i;
- newsize = 8 * (size / 5 + 1) + 1;
- if (newsize > *buflen) {
- if ((newbuf = realloc(*buf, newsize)) == NULL) {
- free(*buf);
- *buf = NULL;
- *buflen = 0;
- return 0;
- }
+ memset(buf, 0, *buflen);
- *buf = newbuf;
- *buflen = newsize;
+ /* how many chars can we encode within the buf */
+ maxsize = 5 * (*buflen / 8 - 1) - 1;
+ /* how big will the encoded data be */
+ newsize = 8 * (size / 5 + 1) + 1;
+ /* if the buffer is too small, eat some of the data */
+ if (*buflen < newsize) {
+ size = maxsize;
}
- p = s = *buf;
- q = (char*)data;
+ p = s = (unsigned char *) buf;
+ q = (unsigned char *)data;
for(i=0;i<size;i+=5) {
- p[0] = cb32[(q[0] >> 3)];
- p[1] = cb32[((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6)];
+ p[0] = cb32[((q[0] & 0xf8) >> 3)];
+ p[1] = cb32[(((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6))];
p[2] = (i+1 < size) ? cb32[((q[1] & 0x3e) >> 1)] : '\0';
p[3] = (i+1 < size) ? cb32[((q[1] & 0x01) << 4) | ((q[2] & 0xf0) >> 4)] : '\0';
p[4] = (i+2 < size) ? cb32[((q[2] & 0x0f) << 1) | ((q[3] & 0x80) >> 7)] : '\0';
- p[5] = (i+3 < size) ? cb32[((q[3] & 0x3e) >> 2)] : '\0';
- p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) > 5)] : '\0';
+ p[5] = (i+3 < size) ? cb32[((q[3] & 0x7c) >> 2)] : '\0';
+ p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) >> 5)] : '\0';
p[7] = (i+4 < size) ? cb32[((q[4] & 0x1f))] : '\0';
q += 5;
p += 8;
}
*p = 0;
- return strlen(s);
-}
-#define DECODE_ERROR 0xffffffff
+ /* store number of bytes from data that was used */
+ *buflen = size;
-static int
-pos(char c)
-{
- const char *p;
- for (p = cb32; *p; p++)
- if (*p == c)
- return p - cb32;
- return -1;
+ return strlen(buf) - 1;
}
+#define DECODE_ERROR 0xffffffff
+#define REV32(x) rev32[(int) (x)]
+
static int
-decode_token(const char *t, char *data)
+decode_token(const unsigned char *t, unsigned char *data, size_t len)
{
- int len;
-
- len = strlen(t);
-
if (len < 2)
return 0;
- data[0] = ((pos(t[0]) & 0x1f) << 3) |
- ((pos(t[1]) & 0x1c) >> 2);
+ data[0] = ((REV32(t[0]) & 0x1f) << 3) |
+ ((REV32(t[1]) & 0x1c) >> 2);
if (len < 4)
return 1;
- data[1] = ((pos(t[1]) & 0x03) << 6) |
- ((pos(t[2]) & 0x1f) << 1) |
- ((pos(t[3]) & 0x10) >> 4);
+ data[1] = ((REV32(t[1]) & 0x03) << 6) |
+ ((REV32(t[2]) & 0x1f) << 1) |
+ ((REV32(t[3]) & 0x10) >> 4);
if (len < 5)
return 2;
- data[2] = ((pos(t[3]) & 0x0f) << 4) |
- ((pos(t[4]) & 0x1e) >> 1);
+ data[2] = ((REV32(t[3]) & 0x0f) << 4) |
+ ((REV32(t[4]) & 0x1e) >> 1);
if (len < 7)
return 3;
- data[3] = ((pos(t[4]) & 0x01) << 7) |
- ((pos(t[5]) & 0x1f) << 2) |
- ((pos(t[6]) & 0x18) >> 3);
+ data[3] = ((REV32(t[4]) & 0x01) << 7) |
+ ((REV32(t[5]) & 0x1f) << 2) |
+ ((REV32(t[6]) & 0x18) >> 3);
if (len < 8)
return 4;
- data[4] = ((pos(t[6]) & 0x07) << 5) |
- ((pos(t[7]) & 0x1f));
+ data[4] = ((REV32(t[6]) & 0x07) << 5) |
+ ((REV32(t[7]) & 0x1f));
return 5;
}
int
-base32_decode(void **buf, size_t *buflen, const char *str)
+base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
{
unsigned char *q;
size_t newsize;
+ size_t maxsize;
const char *p;
- char *newbuf;
+ unsigned char c;
int len;
-
- newsize = 5 * (strlen(str) / 8 + 1) + 1;
- if (newsize > *buflen) {
- if ((newbuf = realloc(*buf, newsize)) == NULL) {
- free(*buf);
- *buf = NULL;
- *buflen = 0;
- return 0;
- }
+ int i;
- *buf = newbuf;
- *buflen = newsize;
+ if (!reverse_init) {
+ for (i = 0; i < 32; i++) {
+ c = cb32[i];
+ rev32[(int) c] = i;
+ }
+ reverse_init = 1;
+ }
+
+ /* chars needed to decode slen */
+ newsize = 5 * (slen / 8 + 1) + 1;
+ /* encoded chars that fit in buf */
+ maxsize = 8 * (*buflen / 5 + 1) + 1;
+ /* if the buffer is too small, eat some of the data */
+ if (*buflen < newsize) {
+ slen = maxsize;
}
- q = *buf;
+ q = buf;
for (p = str; *p && strchr(cb32, *p); p += 8) {
- len = decode_token(p, (char *) q);
+ len = decode_token((unsigned char *) p, (unsigned char *) q, slen);
q += len;
+ slen -= 8;
if (len < 5)
break;
}
*q = '\0';
- return q - (unsigned char *) *buf;
+ return q - (unsigned char *) buf;
}