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?
8 USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
9 USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
10
11 config 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
23 config 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
GLOBALS(long w;unsigned total;unsigned n;unsigned align;)40 GLOBALS(
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
47 static 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
do_base(int fd,char * name)57 static 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
base64_main(void)106 void base64_main(void)
107 {
108 TT.n = 6;
109 TT.align = 3;
110 base64_init(toybuf);
111 loopfiles(toys.optargs, do_base);
112 }
113
base32_main(void)114 void 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