diff options
author | June McEnroe <june@causal.agency> | 2018-12-03 23:05:01 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2018-12-03 23:05:01 -0500 |
commit | a8c30b898c2e4dec02c75a25e72c211d9dba473d (patch) | |
tree | 955596669c860d0843e054c0313a0419e1169431 | |
parent | Call uiShow at init so that TermFocus gets set (diff) | |
download | catgirl-a8c30b898c2e4dec02c75a25e72c211d9dba473d.tar.gz catgirl-a8c30b898c2e4dec02c75a25e72c211d9dba473d.zip |
Implement base64 encoding
Will be used for SASL authentication.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | chat.h | 3 | ||||
-rw-r--r-- | pls.c | 60 |
3 files changed, 64 insertions, 0 deletions
diff --git a/Makefile b/Makefile index e09be8b..cd96001 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ OBJS += ui.o OBJS += url.o TESTS += format.t +TESTS += pls.t TESTS += term.t all: tags $(BINS) test diff --git a/chat.h b/chat.h index b6411d7..6c1cf0f 100644 --- a/chat.h +++ b/chat.h @@ -30,6 +30,8 @@ #define err(...) do { uiHide(); err(__VA_ARGS__); } while (0) #define errx(...) do { uiHide(); errx(__VA_ARGS__); } while (0) +typedef unsigned char byte; + struct { char *host; char *port; @@ -193,6 +195,7 @@ char *awcstombs(const wchar_t *src); char *awcsntombs(const wchar_t *src, size_t nwc); int vaswprintf(wchar_t **ret, const wchar_t *format, va_list ap); int aswprintf(wchar_t **ret, const wchar_t *format, ...); +char *base64(const byte *src, size_t len); // HACK: clang won't check wchar_t *format strings. #ifdef NDEBUG diff --git a/pls.c b/pls.c index d91fc97..4e032c8 100644 --- a/pls.c +++ b/pls.c @@ -131,3 +131,63 @@ int aswprintf(wchar_t **ret, const wchar_t *format, ...) { va_end(ap); return n; } + +static const char Base64[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +char *base64(const byte *src, size_t len) { + char *dst = malloc(1 + 4 * (len + 2) / 3); + if (!dst) return NULL; + size_t i = 0; + while (len > 2) { + dst[i++] = Base64[0x3F & (src[0] >> 2)]; + dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)]; + dst[i++] = Base64[0x3F & (src[1] << 2 | src[2] >> 6)]; + dst[i++] = Base64[0x3F & src[2]]; + src += 3; + len -= 3; + } + if (len) { + dst[i++] = Base64[0x3F & (src[0] >> 2)]; + if (len > 1) { + dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)]; + dst[i++] = Base64[0x3F & (src[1] << 2)]; + } else { + dst[i++] = Base64[0x3F & (src[0] << 4)]; + dst[i++] = '='; + } + dst[i++] = '='; + } + dst[i] = '\0'; + return dst; +} + +#ifdef TEST +#include <assert.h> +#include <string.h> + +int main() { + char *cat = base64((byte *)"cat", 3); + char *ca = base64((byte *)"ca", 2); + char *c = base64((byte *)"c", 1); + assert(cat); + assert(ca); + assert(c); + assert(!strcmp("Y2F0", cat)); + assert(!strcmp("Y2E=", ca)); + assert(!strcmp("Yw==", c)); + free(cat); + free(ca); + free(c); + + char *fzf = base64((byte []) { 0xFF, 0x00, 0xFF }, 3); + char *zfz = base64((byte []) { 0x00, 0xFF, 0x00 }, 3); + assert(fzf); + assert(zfz); + assert(!strcmp("/wD/", fzf)); + assert(!strcmp("AP8A", zfz)); + free(fzf); + free(zfz); +} + +#endif |