From 959151a24dd70fdaffd7039c06dcb81bcc9a56f8 Mon Sep 17 00:00:00 2001 From: leitner Date: Mon, 13 Mar 2017 17:50:19 +0000 Subject: [PATCH] add man page for scan_base64, handle partial blocks better --- textcode/scan_base64.3 | 34 ++++++++++++++++++++++++++++++++++ textcode/scan_base64.c | 31 +++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 textcode/scan_base64.3 diff --git a/textcode/scan_base64.3 b/textcode/scan_base64.3 new file mode 100644 index 0000000..ef6e617 --- /dev/null +++ b/textcode/scan_base64.3 @@ -0,0 +1,34 @@ +.TH scan_base64 3 +.SH NAME +scan_base64 \- decode base64 encoded data +.SH SYNTAX +.B #include + +size_t \fBscan_base64\fP(const char *\fIsrc\fR,char *\fIdest\fR,size_t* \fIdestlen\fR); + +.SH DESCRIPTION +scan_base64 decodes base64 encoded data from src into dest. +It will stop when it encountes any non-valid input characters. +It will then write the number of decoded bytes in dest into *destlen, +and return the number of bytes decoded from src. + +Note that real world base64 encoded data is sometimes permitted to +contain whitespace characters or new lines. This function will not allow +those and return the decoded data until then. + +base64 works by taking 3 bytes of binary input and converting them into +4 bytes of printable ASCII. If the input ends in the middle of a base64 +4-byte-tuple, scan_base64 will disregard it. + +Many base64 variants demand padding in the last block. Some don't. This +implementation will consume padding if it is there, but will not +complain if it is not. + +.SH "RETURN VALUE" +scan_base64 returns the number of bytes successfully scanned and +processed from src. +.SH EXAMPLES +scan_base64("Zm5vcmQ=",buf,&i) -> return 8, i=5, buf="fnord" + +.SH "SEE ALSO" +scan_xlong(3), scan_8long(3), fmt_ulong(3) diff --git a/textcode/scan_base64.c b/textcode/scan_base64.c index e46278d..648d19e 100644 --- a/textcode/scan_base64.c +++ b/textcode/scan_base64.c @@ -15,20 +15,39 @@ static inline int dec(unsigned char x) { size_t scan_base64(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 (;;) { + const char* orig=src; + size_t i,j=0; + for (i=0;;) { int a=dec(*s); if (a<0) { + int equal=(*s=='='); while (*s=='=' && ((s-(const unsigned char*)src)&3)) ++s; + tmp &= ((1<=8) { - *dest=(tmp>>(bits-=8)); - ++dest; + bits-=8; + if (dest) dest[i]=(tmp>>bits); + ++i; + if (!bits) { j=i; orig=s; } } } - *destlen=dest-orig; - return (const char*)s-src; + if (destlen) *destlen=j; + return orig-src; } + +#ifdef UNITTEST +#include +#include +#include + +int main() { + char buf[100]; + size_t i,l; + memset(buf,0,10); assert(scan_base64("Zm5vcmQ=",buf,&l)==8 && l==5 && !memcmp(buf,"fnord",6)); + memset(buf,0,10); assert(scan_base64("Zm5vcmQ",buf,&l)==7 && l==5 && !memcmp(buf,"fnord",6)); +} +#endif