1
2
3
4
5
6
7
8
9#include "libbb.h"
10
11
12#if ENABLE_BASE32
13const char bb_uuenc_tbl_base32[] ALIGN1 = {
14 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
15 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
16 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
17 'Y', 'Z', '2', '3', '4', '5', '6', '7',
18
19};
20#endif
21
22const char bb_uuenc_tbl_base64[] ALIGN1 = {
23 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
24 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
25 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
26 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
27 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
28 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
29 'w', 'x', 'y', 'z', '0', '1', '2', '3',
30 '4', '5', '6', '7', '8', '9', '+', '/',
31 '='
32};
33const char bb_uuenc_tbl_std[] ALIGN1 = {
34 '`', '!', '"', '#', '$', '%', '&', '\'',
35 '(', ')', '*', '+', ',', '-', '.', '/',
36 '0', '1', '2', '3', '4', '5', '6', '7',
37 '8', '9', ':', ';', '<', '=', '>', '?',
38 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
39 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
40 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
41 'X', 'Y', 'Z', '[', '\\',']', '^', '_',
42 '`'
43};
44
45
46
47
48
49
50
51void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl)
52{
53 const unsigned char *s = src;
54
55
56 while (length > 0) {
57 unsigned s1, s2;
58
59
60 s1 = s2 = 0;
61 length -= 3;
62 if (length >= -1) {
63 s1 = s[1];
64 if (length >= 0)
65 s2 = s[2];
66 }
67 *p++ = tbl[s[0] >> 2];
68 *p++ = tbl[((s[0] & 3) << 4) + (s1 >> 4)];
69 *p++ = tbl[((s1 & 0xf) << 2) + (s2 >> 6)];
70 *p++ = tbl[s2 & 0x3f];
71 s += 3;
72 }
73
74 *p = '\0';
75
76 while (length) {
77 *--p = tbl[64];
78 length++;
79 }
80}
81
82
83
84
85
86
87
88
89
90char* FAST_FUNC decode_base64(char *dst, const char **pp_src)
91{
92 const char *src = pp_src ? *pp_src : dst;
93 unsigned ch = 0;
94 unsigned t;
95 int i = 0;
96
97 while ((t = (unsigned char)*src) != '\0') {
98 src++;
99
100
101 if (t >= '0' && t <= '9')
102 t = t - '0' + 52;
103 else if (t >= 'A' && t <= 'Z')
104 t = t - 'A';
105 else if (t >= 'a' && t <= 'z')
106 t = t - 'a' + 26;
107 else if (t == '+')
108 t = 62;
109 else if (t == '/')
110 t = 63;
111 else if (t == '=' && (i == 3 || (i == 2 && *src == '=')))
112
113 t = 0x1000000;
114 else
115
116 continue;
117
118 ch = (ch << 6) | t;
119 i = (i + 1) & 3;
120 if (i == 0) {
121 *dst++ = (char) (ch >> 16);
122 *dst++ = (char) (ch >> 8);
123 *dst++ = (char) ch;
124 if (ch & 0x1000000) {
125 dst--;
126 if (ch & (0x1000000 << 6))
127 dst--;
128 break;
129 }
130 ch = 0;
131 }
132 }
133
134 if (pp_src)
135 *pp_src = src - i;
136 return dst;
137}
138
139#if ENABLE_BASE32
140char* FAST_FUNC decode_base32(char *dst, const char **pp_src)
141{
142 const char *src = *pp_src;
143 uint64_t ch = 0;
144 unsigned t;
145 int i = 0;
146
147 while ((t = (unsigned char)*src) != '\0') {
148 src++;
149
150
151 if (t >= '2' && t <= '7')
152 t = t - '2' + 26;
153 else if (t == '=' && i > 1)
154 t = 0;
155 else {
156 t = (t | 0x20) - 'a';
157 if (t > 25)
158
159 continue;
160 }
161
162 ch = (ch << 5) | t;
163 i = (i + 1) & 7;
164 if (i == 0) {
165 *dst++ = (char) (ch >> 32);
166 if (src[-1] == '=')
167 goto tail;
168 *dst++ = (char) (ch >> 24);
169 *dst++ = (char) (ch >> 16);
170 *dst++ = (char) (ch >> 8);
171 *dst++ = (char) ch;
172 }
173 }
174
175 *pp_src = src - i;
176 return dst;
177 tail:
178 {
179 const char *s = src;
180 while (*--s == '=')
181 i++;
182
183
184
185
186
187
188
189
190
191 *dst++ = (char) (ch >> 24);
192 *dst++ = (char) (ch >> 16);
193 *dst++ = (char) (ch >> 8);
194 *dst++ = (char) ch;
195 dst -= (i+1) * 2 / 3;
196 }
197 *pp_src = src;
198 return dst;
199}
200#endif
201
202
203
204
205
206
207void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
208{
209
210#define exit_char ((int)(signed char)flags)
211#define uu_style_end (flags & BASE64_FLAG_UU_STOP)
212#define base32 (flags & BASE64_32)
213
214
215
216
217
218 enum { BUFFER_SIZE = 80 };
219
220 char buf[BUFFER_SIZE + 2];
221 int term_seen = 0;
222 int in_count = 0;
223
224 while (1) {
225 char *out_tail;
226 const char *in_tail;
227
228 while (in_count < BUFFER_SIZE) {
229 int ch = fgetc(src_stream);
230 if (ch == exit_char) {
231 if (in_count == 0)
232 return;
233 term_seen = 1;
234 break;
235 }
236 if (ch == EOF) {
237 term_seen = 1;
238 break;
239 }
240
241
242
243
244 if (ch <= ' ')
245 break;
246 buf[in_count++] = ch;
247 }
248 buf[in_count] = '\0';
249
250
251 if (uu_style_end && strcmp(buf, "====") == 0)
252 return;
253
254 in_tail = buf;
255#if ENABLE_BASE32
256 if (base32)
257 out_tail = decode_base32(buf, &in_tail);
258 else
259#endif
260 out_tail = decode_base64(buf, &in_tail);
261
262 fwrite(buf, (out_tail - buf), 1, dst_stream);
263
264 if (term_seen) {
265
266 if (*in_tail == '\0')
267 return;
268
269 bb_simple_error_msg_and_die("truncated input");
270 }
271
272
273 in_count = strlen(in_tail);
274 memmove(buf, in_tail, in_count);
275 }
276}
277