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