xref: /aosp_15_r20/external/toybox/toys/other/base64.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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