Author | Jamozed <[email protected]> |
Date | 2021-02-05 11:53:24 |
Commit | 7ce4bd4e51828ad792d9b0eed936957d469db1b4 |
Parent | 2b96ababa2b0cf4e8c2bd4465841007e9848f271 |
base64: Implement base64 decoding
Diffstat
M | src/base64.c | | | 59 | +++++++++++++++++++++++++++++++++++++++-------------------- |
1 files changed, 39 insertions, 20 deletions
diff --git a/src/base64.c b/src/base64.c index 6ec968c..4b42fd8 100644 --- a/src/base64.c +++ b/src/base64.c @@ -1,4 +1,4 @@ -// base64.c, version 0.1.0 +// base64.c, version 1.0.0 // OMKOV coreutils base64 // Copyright (C) 2021, Jakob Wakeling // All rights reserved. @@ -31,17 +31,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. */ /* - TODO Implement Base64 decoding. + TODO Improve or replace fgetb64. */ +#include "lib/base64.h" #include "lib/error.h" #include "lib/optget.h" +#include <ctype.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> -#define VERSION "0.1.0" +#define VERSION "1.0.0" static struct lop lops[] = { { "help", ARG_NUL, 256 }, @@ -57,6 +59,8 @@ static inline int base64(const char *file); static void encodeBase64(FILE *fi); static void decodeBase64(FILE *fi); +static inline size_t fgetb64(uint8_t *buf, size_t len, FILE *fi); + static void hlp(void); static void ver(void); @@ -92,41 +96,56 @@ static inline int base64(const char *file) { if (fi != stdin) { fclose(fi); } return 0; } -/* Encode base64 using fixed size buffers. */ +/* Encode base64 using fixed size buffers */ static void encodeBase64(FILE *fi) { uint8_t ibuf[BUFSIZ * 6]; int l = 0; uint8_t obuf[BUFSIZ * 8 + (BUFSIZ * 8 / 76)]; for (size_t c; (c = fread(ibuf, 1, sizeof (ibuf), fi)) != 0;) { - uint8_t *i = ibuf; uint8_t *j = obuf; + register uint8_t *i = ibuf, *o = obuf; - while (c >= 3) { - *j++ = B64E[i[0] >> 2]; - *j++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)]; - *j++ = B64E[((i[1] & 0x0F) << 2) | (i[2] >> 6)]; - *j++ = B64E[i[2] & 0x3F]; i += 3; + for (; c >= 3; c -= 3) { + *o++ = B64E[i[0] >> 2]; + *o++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)]; + *o++ = B64E[((i[1] & 0x0F) << 2) | (i[2] >> 6)]; + *o++ = B64E[i[2] & 0x3F]; i += 3; - c -= 3; l += 4; if (l == 76) { *j++ = '\n'; l = 0; } + l += 4; if (l == 76) { *o++ = '\n'; l = 0; } } if (c) { - *j++ = B64E[i[0] >> 2]; - if (c == 1) { *j++ = B64E[(i[0] & 0x03) << 4]; *j++ = '='; } + *o++ = B64E[i[0] >> 2]; + + if (c == 1) { + *o++ = B64E[(i[0] & 0x03) << 4]; *o++ = '='; + } else { - *j++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)]; - *j++ = B64E[(i[1] & 0x0F) << 2]; - } *j++ = '='; l += 4; + *o++ = B64E[((i[0] & 0x03) << 4) | (i[1] >> 4)]; + *o++ = B64E[(i[1] & 0x0F) << 2]; + } *o++ = '='; l += 4; } - fwrite(obuf, 1, j - obuf, stdout); + fwrite(obuf, 1, o - obuf, stdout); } if (l) { fputc('\n', stdout); } return; } -/* Decode base64 using fixed size buffers. */ +/* Decode base64 using fixed size buffers */ static void decodeBase64(FILE *fi) { - return; + uint8_t ibuf[BUFSIZ * 8]; uint8_t obuf[BUFSIZ * 6]; + + for (size_t c; (c = fgetb64(ibuf, sizeof (ibuf), fi)) != 0;) { + c = b64decode(obuf, ibuf, c); fwrite(obuf, 1, c, stdout); + } +} + +/* Read valid Base64 characters from a file */ +static inline size_t fgetb64(uint8_t *buf, size_t len, FILE *fi) { + size_t i = 0; for (int c; (c = fgetc(fi)) != EOF;) { + if (isalnum(c) || c == '+' || c == '/') { buf[i++] = c; } + if (i == len) { break; } + } return i; } /* Print help information */ @@ -134,7 +153,7 @@ static void hlp(void) { puts("base64 - base64 encode or decode data\n"); puts("usage: base64 [-d] [file]\n"); puts("options:"); - puts(" -d Decode data (unimplemented)"); + puts(" -d Decode data"); puts(" --help Display help information"); puts(" --version Display version information"); return;