Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/string/base64.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
/*
24
* mime base64 encode/decode
25
*
26
* Glenn Fowler
27
* David Korn
28
* AT&T Research
29
*/
30
31
#include <ast.h>
32
33
#define PAD '='
34
35
#define B64_UC 3
36
#define B64_EC 4
37
#define B64_CHUNK 15
38
#define B64_PAD 64
39
#define B64_SPC 65
40
#define B64_IGN 66
41
42
static unsigned char map[UCHAR_MAX+1];
43
44
static const char alp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
45
46
/*
47
* mime base64 encode
48
*/
49
50
ssize_t
51
base64encode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn)
52
{
53
register unsigned char* fp;
54
register unsigned char* tp;
55
register unsigned char* fe;
56
register unsigned char* te;
57
register unsigned char* tc;
58
register unsigned char* m;
59
register unsigned long b;
60
size_t n;
61
unsigned char tmp[B64_EC * B64_CHUNK];
62
63
m = (unsigned char*)alp;
64
fp = fe = (unsigned char*)fb;
65
if (fz >= 3)
66
{
67
n = fz % 3;
68
fe += fz - n;
69
fz = n;
70
}
71
if (tp = (unsigned char*)tb)
72
{
73
te = tp + tz - B64_EC + 1;
74
n = 0;
75
}
76
else
77
{
78
if (fn)
79
*fn = fp;
80
if (tn)
81
*tn = 0;
82
tp = tmp;
83
te = tp + sizeof(tmp) - B64_EC + 1;
84
n = 1;
85
}
86
for (;;)
87
{
88
tc = tp + B64_EC * B64_CHUNK;
89
do
90
{
91
if (fp >= fe)
92
goto done;
93
if (tp >= te)
94
{
95
if (fn)
96
*fn = fp;
97
if (tn)
98
*tn = tp;
99
n = tp - (unsigned char*)tb + 1;
100
tp = tmp;
101
te = tp + sizeof(tmp) - B64_EC + 1;
102
}
103
b = *fp++ << 16;
104
b |= *fp++ << 8;
105
b |= *fp++;
106
*tp++ = m[b >> 18];
107
*tp++ = m[(b >> 12) & 077];
108
*tp++ = m[(b >> 6) & 077];
109
*tp++ = m[b & 077];
110
} while (tp < tc);
111
if (n)
112
{
113
n += tp - tmp + (fp < fe);
114
tp = tmp;
115
}
116
else
117
*tp++ = '\n';
118
}
119
done:
120
if (fz)
121
{
122
if (tp >= te)
123
{
124
if (fn)
125
*fn = fp;
126
if (tn)
127
*tn = tp;
128
n = tp - (unsigned char*)tb + 1;
129
tp = tmp;
130
te = tp + sizeof(tmp) - B64_EC + 1;
131
}
132
b = *fp++ << 16;
133
if (fz == 2)
134
b |= *fp++ << 8;
135
*tp++ = m[b >> 18];
136
*tp++ = m[(b >> 12) & 077];
137
*tp++ = (fz == 2) ? m[(b >> 6) & 077] : PAD;
138
*tp++ = PAD;
139
}
140
if (n)
141
n += (tp - tmp) - 1;
142
else
143
{
144
if (tp > (unsigned char*)tb && *(tp - 1) == '\n')
145
tp--;
146
if (tp < te)
147
*tp = 0;
148
n = tp - (unsigned char*)tb;
149
if (tn)
150
*tn = tp;
151
if (fn)
152
*fn = fp;
153
}
154
return n;
155
}
156
157
/*
158
* mime base64 decode
159
*/
160
161
ssize_t
162
base64decode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn)
163
{
164
register unsigned char* fp;
165
register unsigned char* tp;
166
register unsigned char* fe;
167
register unsigned char* te;
168
register unsigned char* tx;
169
register unsigned char* m;
170
register int c;
171
register int state;
172
register unsigned long v;
173
unsigned char* fc;
174
ssize_t n;
175
176
if (!(m = map)[0])
177
{
178
memset(m, B64_IGN, sizeof(map));
179
for (tp = (unsigned char*)alp; c = *tp; tp++)
180
m[c] = tp - (unsigned char*)alp;
181
m[PAD] = B64_PAD;
182
m[' '] = m['\t'] = m['\n'] = B64_SPC;
183
}
184
fp = (unsigned char*)fb;
185
fe = fp + fz;
186
if (tp = (unsigned char*)tb)
187
{
188
te = tp + tz;
189
if (tz > 2)
190
tz = 2;
191
tx = te - tz;
192
n = 0;
193
}
194
else
195
{
196
te = tx = tp;
197
n = 1;
198
}
199
for (;;)
200
{
201
fc = fp;
202
state = 0;
203
v = 0;
204
while (fp < fe)
205
{
206
if ((c = m[*fp++]) < 64)
207
{
208
v = (v << 6) | c;
209
if (++state == 4)
210
{
211
if (tp >= tx)
212
{
213
if (n)
214
n += 3;
215
else
216
{
217
n = tp - (unsigned char*)tb + 4;
218
if (tp < te)
219
{
220
*tp++ = (v >> 16);
221
if (tp < te)
222
{
223
*tp++ = (v >> 8);
224
if (tp < te)
225
*tp++ = (v);
226
}
227
}
228
if (tn)
229
*tn = tp;
230
if (fn)
231
*fn = fc;
232
}
233
}
234
else
235
{
236
*tp++ = (v >> 16);
237
*tp++ = (v >> 8);
238
*tp++ = (v);
239
}
240
fc = fp;
241
state = 0;
242
v = 0;
243
}
244
}
245
else if (c == B64_PAD)
246
break;
247
}
248
switch (state)
249
{
250
case 0:
251
goto done;
252
case 2:
253
if (tp < te)
254
*tp++ = v >> 4;
255
else if (n)
256
n++;
257
else
258
{
259
n = tp - (unsigned char*)tb + 2;
260
if (tn)
261
*tn = tp;
262
if (fn)
263
*fn = fc;
264
}
265
break;
266
case 3:
267
if (tp < te)
268
{
269
*tp++ = v >> 10;
270
if (tp < te)
271
*tp++ = v >> 2;
272
else
273
{
274
n = tp - (unsigned char*)tb + 2;
275
if (tn)
276
*tn = tp;
277
if (fn)
278
*fn = fc;
279
}
280
}
281
else if (n)
282
n += 2;
283
else
284
{
285
n = tp - (unsigned char*)tb + 3;
286
if (tn)
287
*tn = tp;
288
if (fn)
289
*fn = fc;
290
}
291
break;
292
}
293
while (fp < fe && ((c = m[*fp++]) == B64_PAD || c == B64_SPC));
294
if (fp >= fe || c >= 64)
295
break;
296
fp--;
297
}
298
done:
299
if (n)
300
n--;
301
else
302
{
303
if (tp < te)
304
*tp = 0;
305
n = tp - (unsigned char*)tb;
306
if (fn)
307
*fn = fp;
308
if (tn)
309
*tn = tp;
310
}
311
return n;
312
}
313
314