1 /* base64.c - Encode and decode base64
2 *
3 * Copyright 2014 Rob Landley <[email protected]>
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|TOYFLAG_LINEBUF))
9 USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
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
43 unsigned total;
44 unsigned n; // number of bits used in encoding. 5 for base32, 6 for base64
45 unsigned align; // number of bits to align to
46 )
47
48 static void wraputchar(int c, int *x)
49 {
50 putchar(c);
51 TT.total++;
52 if (TT.w && ++*x == TT.w) {
53 *x = 0;
54 xputc('\n');
55 };
56 }
57
do_base(int fd,char * name)58 static void do_base(int fd, char *name)
59 {
60 int out = 0, bits = 0, x = 0, i, len;
61 char *buf = toybuf+128;
62
63 TT.total = 0;
64
65 for (;;) {
66 // If no more data, flush buffer
67 if (!(len = xread(fd, buf, sizeof(toybuf)-128))) {
68 if (!FLAG(d)) {
69 if (bits) wraputchar(toybuf[out<<(TT.n-bits)], &x);
70 while (TT.total&TT.align) wraputchar('=', &x);
71 if (x) xputc('\n');
72 }
73
74 return;
75 }
76
77 for (i=0; i<len; i++) {
78 if (FLAG(d)) {
79 if (buf[i] == '=') return;
80
81 if ((x = stridx(toybuf, buf[i])) != -1) {
82 out = (out<<TT.n) + x;
83 bits += TT.n;
84 if (bits >= 8) {
85 putchar(out >> (bits -= 8));
86 out &= (1<<bits)-1;
87 if (ferror(stdout)) perror_exit(0);
88 }
89
90 continue;
91 }
92 if (buf[i] == '\n' || FLAG(i)) continue;
93
94 break;
95 } else {
96 out = (out<<8) + buf[i];
97 bits += 8;
98 while (bits >= TT.n) {
99 wraputchar(toybuf[out >> (bits -= TT.n)], &x);
100 out &= (1<<bits)-1;
101 }
102 }
103 }
104 }
105 }
106
base64_main(void)107 void base64_main(void)
108 {
109 TT.n = 6;
110 TT.align = 3;
111 base64_init(toybuf);
112 loopfiles(toys.optargs, do_base);
113 }
114
base32_main(void)115 void base32_main(void)
116 {
117 int i;
118
119 TT.n = 5;
120 TT.align = 7;
121 for (i = 0; i<32; i++) toybuf[i] = i+(i<26 ? 'A' : 24);
122 loopfiles(toys.optargs, do_base);
123 }
124