10f66f451Sopenharmony_ci/* base64.c - Encode and decode base64 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2014 Rob Landley <rob@landley.net> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * See https://tools.ietf.org/html/rfc4648 60f66f451Sopenharmony_ci 70f66f451Sopenharmony_ci// These optflags have to match. Todo: cleanup and collapse together? 80f66f451Sopenharmony_ciUSE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN)) 90f66f451Sopenharmony_ciUSE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN)) 100f66f451Sopenharmony_ci 110f66f451Sopenharmony_ciconfig BASE64 120f66f451Sopenharmony_ci bool "base64" 130f66f451Sopenharmony_ci default y 140f66f451Sopenharmony_ci help 150f66f451Sopenharmony_ci usage: base64 [-di] [-w COLUMNS] [FILE...] 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci Encode or decode in base64. 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci -d Decode 200f66f451Sopenharmony_ci -i Ignore non-alphabetic characters 210f66f451Sopenharmony_ci -w Wrap output at COLUMNS (default 76 or 0 for no wrap) 220f66f451Sopenharmony_ci 230f66f451Sopenharmony_ciconfig BASE32 240f66f451Sopenharmony_ci bool "base32" 250f66f451Sopenharmony_ci default y 260f66f451Sopenharmony_ci help 270f66f451Sopenharmony_ci usage: base32 [-di] [-w COLUMNS] [FILE...] 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci Encode or decode in base32. 300f66f451Sopenharmony_ci 310f66f451Sopenharmony_ci -d Decode 320f66f451Sopenharmony_ci -i Ignore non-alphabetic characters 330f66f451Sopenharmony_ci -w Wrap output at COLUMNS (default 76 or 0 for no wrap) 340f66f451Sopenharmony_ci*/ 350f66f451Sopenharmony_ci 360f66f451Sopenharmony_ci#define FOR_base64 370f66f451Sopenharmony_ci#define FORCE_FLAGS 380f66f451Sopenharmony_ci#include "toys.h" 390f66f451Sopenharmony_ci 400f66f451Sopenharmony_ciGLOBALS( 410f66f451Sopenharmony_ci long w; 420f66f451Sopenharmony_ci unsigned total; 430f66f451Sopenharmony_ci unsigned n; // number of bits used in encoding. 5 for base32, 6 for base64 440f66f451Sopenharmony_ci unsigned align; // number of bits to align to 450f66f451Sopenharmony_ci) 460f66f451Sopenharmony_ci 470f66f451Sopenharmony_cistatic void wraputchar(int c, int *x) 480f66f451Sopenharmony_ci{ 490f66f451Sopenharmony_ci putchar(c); 500f66f451Sopenharmony_ci TT.total++; 510f66f451Sopenharmony_ci if (TT.w && ++*x == TT.w) { 520f66f451Sopenharmony_ci *x = 0; 530f66f451Sopenharmony_ci xputc('\n'); 540f66f451Sopenharmony_ci }; 550f66f451Sopenharmony_ci} 560f66f451Sopenharmony_ci 570f66f451Sopenharmony_cistatic void do_base(int fd, char *name) 580f66f451Sopenharmony_ci{ 590f66f451Sopenharmony_ci int out = 0, bits = 0, x = 0, i, len; 600f66f451Sopenharmony_ci char *buf = toybuf+128; 610f66f451Sopenharmony_ci 620f66f451Sopenharmony_ci TT.total = 0; 630f66f451Sopenharmony_ci 640f66f451Sopenharmony_ci for (;;) { 650f66f451Sopenharmony_ci // If no more data, flush buffer 660f66f451Sopenharmony_ci if (!(len = xread(fd, buf, sizeof(toybuf)-128))) { 670f66f451Sopenharmony_ci if (!FLAG(d)) { 680f66f451Sopenharmony_ci if (bits) wraputchar(toybuf[out<<(TT.n-bits)], &x); 690f66f451Sopenharmony_ci while (TT.total&TT.align) wraputchar('=', &x); 700f66f451Sopenharmony_ci if (x) xputc('\n'); 710f66f451Sopenharmony_ci } 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_ci return; 740f66f451Sopenharmony_ci } 750f66f451Sopenharmony_ci 760f66f451Sopenharmony_ci for (i=0; i<len; i++) { 770f66f451Sopenharmony_ci if (FLAG(d)) { 780f66f451Sopenharmony_ci if (buf[i] == '=') return; 790f66f451Sopenharmony_ci 800f66f451Sopenharmony_ci if ((x = stridx(toybuf, buf[i])) != -1) { 810f66f451Sopenharmony_ci out = (out<<TT.n) + x; 820f66f451Sopenharmony_ci bits += TT.n; 830f66f451Sopenharmony_ci if (bits >= 8) { 840f66f451Sopenharmony_ci putchar(out >> (bits -= 8)); 850f66f451Sopenharmony_ci out &= (1<<bits)-1; 860f66f451Sopenharmony_ci if (ferror(stdout)) perror_exit(0); 870f66f451Sopenharmony_ci } 880f66f451Sopenharmony_ci 890f66f451Sopenharmony_ci continue; 900f66f451Sopenharmony_ci } 910f66f451Sopenharmony_ci if (buf[i] == '\n' || FLAG(i)) continue; 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci break; 940f66f451Sopenharmony_ci } else { 950f66f451Sopenharmony_ci out = (out<<8) + buf[i]; 960f66f451Sopenharmony_ci bits += 8; 970f66f451Sopenharmony_ci while (bits >= TT.n) { 980f66f451Sopenharmony_ci wraputchar(toybuf[out >> (bits -= TT.n)], &x); 990f66f451Sopenharmony_ci out &= (1<<bits)-1; 1000f66f451Sopenharmony_ci } 1010f66f451Sopenharmony_ci } 1020f66f451Sopenharmony_ci } 1030f66f451Sopenharmony_ci } 1040f66f451Sopenharmony_ci} 1050f66f451Sopenharmony_ci 1060f66f451Sopenharmony_civoid base64_main(void) 1070f66f451Sopenharmony_ci{ 1080f66f451Sopenharmony_ci TT.n = 6; 1090f66f451Sopenharmony_ci TT.align = 3; 1100f66f451Sopenharmony_ci base64_init(toybuf); 1110f66f451Sopenharmony_ci loopfiles(toys.optargs, do_base); 1120f66f451Sopenharmony_ci} 1130f66f451Sopenharmony_ci 1140f66f451Sopenharmony_civoid base32_main(void) 1150f66f451Sopenharmony_ci{ 1160f66f451Sopenharmony_ci int i; 1170f66f451Sopenharmony_ci 1180f66f451Sopenharmony_ci TT.n = 5; 1190f66f451Sopenharmony_ci TT.align = 7; 1200f66f451Sopenharmony_ci for (i = 0; i<32; i++) toybuf[i] = i+(i<26 ? 'A' : 24); 1210f66f451Sopenharmony_ci loopfiles(toys.optargs, do_base); 1220f66f451Sopenharmony_ci} 123