summaryrefslogtreecommitdiff
path: root/base64.c
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-06-02 17:37:16 -0700
committerJohn Denker <jsd@av8n.com>2012-06-02 17:37:16 -0700
commit22d3da72492f2b0939d11f1bf0a2b23a4f69ec63 (patch)
treebc4c8ea163c47050e92ef55b8b9f33129f78b111 /base64.c
parent3fa6a9210404ed793ea4a3fd3883a2e6bbf7cb7f (diff)
apply the big auth patch
Diffstat (limited to 'base64.c')
-rw-r--r--base64.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/base64.c b/base64.c
new file mode 100644
index 0000000..fbce145
--- /dev/null
+++ b/base64.c
@@ -0,0 +1,90 @@
+#include "base64.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "str.h"
+
+static char *b64alpha =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define B64PAD '='
+
+/* returns 0 ok, 1 illegal, -1 problem */
+
+int b64decode(in,l,out)
+const unsigned char *in;
+int l;
+stralloc *out; /* not null terminated */
+{
+ int i, j;
+ unsigned char a[4];
+ unsigned char b[3];
+ char *s;
+
+ if (l == 0)
+ {
+ if (!stralloc_copys(out,"")) return -1;
+ return 0;
+ }
+
+ if (!stralloc_ready(out,l + 2)) return -1; /* XXX generous */
+ s = out->s;
+
+ for (i = 0;i < l;i += 4) {
+ for (j = 0;j < 4;j++)
+ if ((i + j) < l && in[i + j] != B64PAD)
+ {
+ a[j] = str_chr(b64alpha,in[i + j]);
+ if (a[j] > 63) return 1;
+ }
+ else a[j] = 0;
+
+ b[0] = (a[0] << 2) | (a[1] >> 4);
+ b[1] = (a[1] << 4) | (a[2] >> 2);
+ b[2] = (a[2] << 6) | (a[3]);
+
+ *s++ = b[0];
+
+ if (in[i + 1] == B64PAD) break;
+ *s++ = b[1];
+
+ if (in[i + 2] == B64PAD) break;
+ *s++ = b[2];
+ }
+ out->len = s - out->s;
+ while (out->len && !out->s[out->len - 1]) --out->len; /* XXX avoid? */
+ return 0;
+}
+
+int b64encode(in,out)
+stralloc *in;
+stralloc *out; /* not null terminated */
+{
+ unsigned char a, b, c;
+ int i;
+ char *s;
+
+ if (in->len == 0)
+ {
+ if (!stralloc_copys(out,"")) return -1;
+ return 0;
+ }
+
+ if (!stralloc_ready(out,in->len / 3 * 4 + 4)) 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 & 15) << 2) | (c >> 6)];
+
+ if (i + 2 >= in->len) *s++ = B64PAD;
+ else *s++ = b64alpha[c & 63];
+ }
+ out->len = s - out->s;
+ return 0;
+}