From 7f829a36bce77da5a0709f9b3dde265ac5a6ce29 Mon Sep 17 00:00:00 2001 From: leitner Date: Sun, 28 Feb 2016 12:24:47 +0000 Subject: [PATCH] add base64url support --- test/textcode.c | 9 +++++++++ textcode/base64url.c | 1 + textcode/fmt_base64url.c | 24 ++++++++++++++++++++++++ textcode/scan_base64.c | 2 +- textcode/scan_base64url.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 textcode/base64url.c create mode 100644 textcode/fmt_base64url.c create mode 100644 textcode/scan_base64url.c diff --git a/test/textcode.c b/test/textcode.c index daefe65..90244b8 100644 --- a/test/textcode.c +++ b/test/textcode.c @@ -1,7 +1,10 @@ #include "array.h" #include "textcode.h" +#include +#include #include #include +#include array a; @@ -26,5 +29,11 @@ int main() { buf[n]=0; puts(buf); + assert(fmt_base64(buf,"fnörd",6)==8 && !memcmp(buf,"Zm7DtnJk",8)); + assert(scan_base64("Zm7DtnJk",buf,&n)==8 && n==6 && !memcmp(buf,"fnörd",6)); + assert(fmt_base64(buf,"x",1)==4 && !memcmp(buf,"eA==",4)); + assert(scan_base64("eA====",buf,&n)==4 && n==1 && buf[0]=='x'); + assert(fmt_base64url(buf,"\xef\xbf\xbdx",4)==6 && !memcmp(buf,"77-9eA",6)); + assert(scan_base64url("77-9eA",buf,&n)==6 && n==4 && !memcmp(buf,"\xef\xbf\xbdx",4)); return 0; } diff --git a/textcode/base64url.c b/textcode/base64url.c new file mode 100644 index 0000000..4e352d4 --- /dev/null +++ b/textcode/base64url.c @@ -0,0 +1 @@ +const char base64url[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="; diff --git a/textcode/fmt_base64url.c b/textcode/fmt_base64url.c new file mode 100644 index 0000000..1ddbe66 --- /dev/null +++ b/textcode/fmt_base64url.c @@ -0,0 +1,24 @@ +#include "fmt.h" +#include "textcode.h" +#include "haveinline.h" + +size_t fmt_base64url(char* dest,const char* src,size_t len) { + register const unsigned char* s=(const unsigned char*) src; + unsigned short bits=0,temp=0; + size_t written=0,i; + if (!dest) return (len>((size_t)-1)/2)?(size_t)-1:((len+2)/3)*4; + for (i=0; i6) { + dest[written]=base64url[((temp>>(bits-6))&63)]; + ++written; bits-=6; + } + } + if (bits) { + temp<<=(6-bits); + dest[written]=base64url[temp&63]; + ++written; + } + /* no padding for base64url */ + return written; +} diff --git a/textcode/scan_base64.c b/textcode/scan_base64.c index ac28e35..e46278d 100644 --- a/textcode/scan_base64.c +++ b/textcode/scan_base64.c @@ -19,7 +19,7 @@ size_t scan_base64(const char *src,char *dest,size_t *destlen) { for (;;) { int a=dec(*s); if (a<0) { - while (*s=='=') ++s; + while (*s=='=' && ((s-(const unsigned char*)src)&3)) ++s; break; } tmp=(tmp<<6)|a; bits+=6; diff --git a/textcode/scan_base64url.c b/textcode/scan_base64url.c new file mode 100644 index 0000000..f1c1c5f --- /dev/null +++ b/textcode/scan_base64url.c @@ -0,0 +1,31 @@ +#include "textcode.h" +#include "haveinline.h" + +static inline int dec(unsigned char x) { + if (x>='A' && x<='Z') return x-'A'; + if (x>='a' && x<='z') return x-'a'+26; + if (x>='0' && x<='9') return x-'0'+26+26; + switch (x) { + case '-': return 62; + case '_': return 63; + default: return -1; + } +} + +size_t scan_base64url(const char *src,char *dest,size_t *destlen) { + unsigned short tmp=0,bits=0; + register const unsigned char* s=(const unsigned char*) src; + const char* orig=dest; + for (;;) { + int a=dec(*s); + if (a<0) break; + tmp=(tmp<<6)|a; bits+=6; + ++s; + if (bits>=8) { + *dest=(tmp>>(bits-=8)); + ++dest; + } + } + *destlen=dest-orig; + return (const char*)s-src; +}