summaryrefslogtreecommitdiff
path: root/src/base64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base64.c')
-rw-r--r--src/base64.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/base64.c b/src/base64.c
new file mode 100644
index 0000000..fd38fe3
--- /dev/null
+++ b/src/base64.c
@@ -0,0 +1,119 @@
+#include "base64.h"
+#include "str.h"
+
+static char *b64alpha =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define B64PAD '='
+
+/* returns 0 ok, 1 illegal, -1 problem */
+
+int b64decode(const unsigned char *in,int l,stralloc *out)
+/* stralloc *out => not null terminated */
+{
+ int p = 0;
+ int n;
+ unsigned int x;
+ int i, j;
+ char *s;
+ unsigned char b[3];
+
+ if (l == 0) {
+ if (!stralloc_copys(out,"")) return -1;
+ return 0;
+ }
+
+ while (in[l-1] == B64PAD) {
+ p ++;
+ l--;
+ }
+
+ n = (l + p) / 4;
+ i = (n * 3) - p;
+ if (!stralloc_ready(out,i)) return -1;
+ out->len = i;
+ s = out->s;
+
+ for (i = 0; i < n - 1; i++) {
+ x = 0;
+ for (j = 0; j < 4; j++) {
+ if (in[j] >= 'A' && in[j] <= 'Z')
+ x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
+ else if (in[j] >= 'a' && in[j] <= 'z')
+ x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
+ else if (in[j] >= '0' && in[j] <= '9')
+ x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
+ else if (in[j] == '+')
+ x = (x << 6) + 62;
+ else if (in[j] == '/')
+ x = (x << 6) + 63;
+ else if (in[j] == '=')
+ x = (x << 6);
+ else return 1;
+ }
+
+ s[2] = (unsigned char)(x & 255); x >>= 8;
+ s[1] = (unsigned char)(x & 255); x >>= 8;
+ s[0] = (unsigned char)(x & 255); x >>= 8;
+ s += 3; in += 4;
+ }
+
+ x = 0;
+ for (j = 0; j < 4; j++) {
+ if (in[j] >= 'A' && in[j] <= 'Z')
+ x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
+ else if (in[j] >= 'a' && in[j] <= 'z')
+ x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
+ else if (in[j] >= '0' && in[j] <= '9')
+ x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
+ else if (in[j] == '+')
+ x = (x << 6) + 62;
+ else if (in[j] == '/')
+ x = (x << 6) + 63;
+ else if (in[j] == '=')
+ x = (x << 6);
+ else return 1;
+ }
+
+ b[2] = (unsigned char)(x & 255); x >>= 8;
+ b[1] = (unsigned char)(x & 255); x >>= 8;
+ b[0] = (unsigned char)(x & 255); x >>= 8;
+
+ for (i = 0; i < 3 - p; i++)
+ s[i] = b[i];
+
+ return 0;
+}
+
+int b64encode(stralloc *in,stralloc *out)
+{
+ unsigned char a, b, c;
+ int i;
+ char *s;
+
+ if (in->len == 0)
+ {
+ if (!stralloc_copys(out,"")) return -1;
+ return 0;
+ }
+
+ i = in->len / 3 * 4 + 4;
+ if (!stralloc_ready(out,i)) return -1;
+ s = out->s;
+
+ for (i = 0; i < in->len; i += 3) {
+ a = in->s[i];
+ b = i + 1 < in->len ? in->s[i + 1] : 0;
+ c = i + 2 < in->len ? in->s[i + 2] : 0;
+
+ *s++ = b64alpha[a >> 2];
+ *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
+
+ if (i + 1 >= in->len) *s++ = B64PAD;
+ else *s++ = b64alpha[((b & 0x0f) << 2) | (c >> 6)];
+
+ if (i + 2 >= in->len) *s++ = B64PAD;
+ else *s++ = b64alpha[c & 0x3f];
+ }
+ out->len = s - out->s;
+ return 0;
+}