[MINOR] Base64 decode
Implement Base64 decoding with a reverse table.
The function accepts and decodes classic base64 strings, which
can be composed from many streams as long each one is properly
padded, for example: SGVsbG8=IEhBUHJveHk=IQ==
diff --git a/include/common/base64.h b/include/common/base64.h
index bd77c68..e668001 100644
--- a/include/common/base64.h
+++ b/include/common/base64.h
@@ -17,6 +17,8 @@
#include <common/config.h>
int a2base64(char *in, int ilen, char *out, int olen);
+int base64dec(const char *in, size_t ilen, char *out, size_t olen);
+
extern const char base64tab[];
#endif /* _COMMON_BASE64_H */
diff --git a/src/base64.c b/src/base64.c
index e012622..ea244a2 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -1,7 +1,8 @@
/*
- * Ascii to Base64 conversion as described in RFC1421.
+ * ASCII <-> Base64 conversion as described in RFC1421.
*
* Copyright 2006-2008 Willy Tarreau <w@1wt.eu>
+ * Copyright 2009-2010 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -10,10 +11,19 @@
*
*/
+#include <stdlib.h>
+#include <string.h>
+
#include <common/base64.h>
#include <common/config.h>
+#define B64BASE '#' /* arbitrary chosen base value */
+#define B64CMIN '+'
+#define B64CMAX 'z'
+#define B64PADV 64 /* Base64 chosen special pad value */
+
const char base64tab[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+const char base64rev[]="b###cXYZ[\\]^_`a###d###$%&'()*+,-./0123456789:;<=######>?@ABCDEFGHIJKLMNOPQRSTUVW";
/* Encodes <ilen> bytes from <in> to <out> for at most <olen> chars (including
* the trailing zero). Returns the number of bytes written. No check is made
@@ -57,3 +67,71 @@
return convlen;
}
+
+/* Decodes <ilen> bytes from <in> to <out> for at most <olen> chars.
+ * Returns the number of bytes converted. No check is made for
+ * <in> or <out> to be NULL. Returns -1 if <in> is invalid or ilen
+ * has wrong size, -2 if <olen> is too short.
+ * 1 to 3 output bytes are produced for 4 input bytes.
+ */
+int base64dec(const char *in, size_t ilen, char *out, size_t olen) {
+
+ unsigned char t[4];
+ signed char b;
+ int convlen = 0, i = 0, pad = 0;
+
+ if (ilen % 4)
+ return -1;
+
+ if (olen < ilen / 4 * 3)
+ return -2;
+
+ while (ilen) {
+
+ /* if (*p < B64CMIN || *p > B64CMAX) */
+ b = (signed char)*in - B64CMIN;
+ if ((unsigned char)b > (B64CMAX-B64CMIN))
+ return -1;
+
+ b = base64rev[b] - B64BASE - 1;
+
+ /* b == -1: invalid character */
+ if (b < 0)
+ return -1;
+
+ /* padding has to be continous */
+ if (pad && b != B64PADV)
+ return -1;
+
+ /* valid padding: "XX==" or "XXX=", but never "X===" or "====" */
+ if (pad && i < 2)
+ return -1;
+
+ if (b == B64PADV)
+ pad++;
+
+ t[i++] = b;
+
+ if (i == 4) {
+ /*
+ * WARNING: we allow to write little more data than we
+ * should, but the checks from the beginning of the
+ * functions guarantee that we can safely do that.
+ */
+
+ /* xx000000 xx001111 xx111122 xx222222 */
+ out[convlen] = ((t[0] << 2) + (t[1] >> 4));
+ out[convlen+1] = ((t[1] << 4) + (t[2] >> 2));
+ out[convlen+2] = ((t[2] << 6) + (t[3] >> 0));
+
+ convlen += 3-pad;
+
+ pad = i = 0;
+ }
+
+ in++;
+ ilen--;
+ }
+
+ return convlen;
+}