toybox/toys/other/base64.c
<<
>>
Prefs
   1/* base64.c - Encode and decode base64
   2 *
   3 * Copyright 2014 Rob Landley <rob@landley.net>
   4 *
   5 * See https://tools.ietf.org/html/rfc4648
   6
   7// These optflags have to match. Todo: cleanup and collapse together?
   8USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
   9USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
  10
  11config BASE64
  12  bool "base64"
  13  default y
  14  help
  15    usage: base64 [-di] [-w COLUMNS] [FILE...]
  16
  17    Encode or decode in base64.
  18
  19    -d  Decode
  20    -i  Ignore non-alphabetic characters
  21    -w  Wrap output at COLUMNS (default 76 or 0 for no wrap)
  22
  23config BASE32
  24  bool "base32"
  25  default y
  26  help
  27    usage: base32 [-di] [-w COLUMNS] [FILE...]
  28
  29    Encode or decode in base32.
  30
  31    -d  Decode
  32    -i  Ignore non-alphabetic characters
  33    -w  Wrap output at COLUMNS (default 76 or 0 for no wrap)
  34*/
  35
  36#define FOR_base64
  37#define FORCE_FLAGS
  38#include "toys.h"
  39
  40GLOBALS(
  41  long w;
  42  unsigned total;
  43  unsigned n;  // number of bits used in encoding. 5 for base32, 6 for base64
  44  unsigned align;  // number of bits to align to
  45)
  46
  47static void wraputchar(int c, int *x)
  48{
  49  putchar(c);
  50  TT.total++;
  51  if (TT.w && ++*x == TT.w) {
  52    *x = 0;
  53    xputc('\n');
  54  };
  55}
  56
  57static void do_base(int fd, char *name)
  58{
  59  int out = 0, bits = 0, x = 0, i, len;
  60  char *buf = toybuf+128;
  61
  62  TT.total = 0;
  63
  64  for (;;) {
  65    // If no more data, flush buffer
  66    if (!(len = xread(fd, buf, sizeof(toybuf)-128))) {
  67      if (!FLAG(d)) {
  68        if (bits) wraputchar(toybuf[out<<(TT.n-bits)], &x);
  69        while (TT.total&TT.align) wraputchar('=', &x);
  70        if (x) xputc('\n');
  71      }
  72
  73      return;
  74    }
  75
  76    for (i=0; i<len; i++) {
  77      if (FLAG(d)) {
  78        if (buf[i] == '=') return;
  79
  80        if ((x = stridx(toybuf, buf[i])) != -1) {
  81          out = (out<<TT.n) + x;
  82          bits += TT.n;
  83          if (bits >= 8) {
  84            putchar(out >> (bits -= 8));
  85            out &= (1<<bits)-1;
  86            if (ferror(stdout)) perror_exit(0);
  87          }
  88
  89          continue;
  90        }
  91        if (buf[i] == '\n' || FLAG(i)) continue;
  92
  93        break;
  94      } else {
  95        out = (out<<8) + buf[i];
  96        bits += 8;
  97        while (bits >= TT.n) {
  98          wraputchar(toybuf[out >> (bits -= TT.n)], &x);
  99          out &= (1<<bits)-1;
 100        }
 101      }
 102    }
 103  }
 104}
 105
 106void base64_main(void)
 107{
 108  TT.n = 6;
 109  TT.align = 3;
 110  base64_init(toybuf);
 111  loopfiles(toys.optargs, do_base);
 112}
 113
 114void base32_main(void)
 115{
 116  int i;
 117
 118  TT.n = 5;
 119  TT.align = 7;
 120  for (i = 0; i<32; i++) toybuf[i] = i+(i<26 ? 'A' : 24);
 121  loopfiles(toys.optargs, do_base);
 122}
 123