2 * Heirloom mailx - a mail user agent derived from Berkeley Mail.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 Steffen "Daode" Nurpmeso.
8 * These base64 routines are derived from the metamail-2.7 sources which
9 * state the following copyright notice:
11 * Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
13 * Permission to use, copy, modify, and distribute this material
14 * for any purpose and without fee is hereby granted, provided
15 * that the above copyright notice and this permission notice
16 * appear in all copies, and that the name of Bellcore not be
17 * used in advertising or publicity pertaining to this
18 * material without the specific, prior written permission
19 * of an authorized representative of Bellcore. BELLCORE
20 * MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
21 * OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
22 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
27 static char sccsid
[] = "@(#)base64.c 2.14 (gritter) 4/21/06";
32 * Mail -- a mail program
40 static const char b64table
[] =
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
42 static const signed char b64index
[] = {
43 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
44 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
45 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
46 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
47 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
48 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
49 -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
50 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
53 #define char64(c) ((c) < 0 ? -1 : b64index[(int)(c)])
55 static signed char *ctob64(unsigned char *p
, int pad
);
58 * Convert three characters to base64.
61 ctob64(unsigned char *p
, int pad
)
63 static signed char b64
[4];
65 b64
[0] = b64table
[p
[0] >> 2];
66 b64
[1] = b64table
[((p
[0] & 0x3) << 4) | ((p
[1] & 0xF0) >> 4)];
68 b64
[1] = b64table
[(p
[0] & 0x3) << 4];
69 b64
[2] = b64
[3] = '=';
70 } else if (pad
== 1) {
71 b64
[2] = b64table
[((p
[1] & 0xF) << 2)];
74 b64
[2] = b64table
[((p
[1] & 0xF) << 2) | ((p
[2] & 0xC0) >> 6)];
75 b64
[3] = b64table
[p
[2] & 0x3F];
81 strtob64(const char *p
)
83 return memtob64(p
, strlen(p
));
87 memtob64(const void *vp
, size_t isz
)
93 int i
, l
= 0, sz
= 0, pads
;
102 for (pads
= 2, i
= 0; i
<= 2; i
++, pads
--) {
107 h
= ctob64((unsigned char *)q
, pads
);
109 rs
= srealloc(rs
, sz
= l
+ 100);
110 for (i
= 0; i
< 4; i
++)
118 * Write to a file converting to base64. The input must be aligned
119 * e.g. at 972 character bounds.
122 mime_write_tob64(struct str
*in
, FILE *fo
, int is_header
)
124 char *p
, *upper
, q
[3];
130 upper
= in
->s
+ in
->l
;
131 for (p
= in
->s
, l
= 0; p
< upper
; ) {
132 for (pads
= 2, i
= 0; i
<= 2; i
++, pads
--) {
137 h
= ctob64((unsigned char *)q
, pads
);
138 fwrite(h
, sizeof(char), 4, fo
);
141 putc('\n', fo
), sz
++;
145 if (l
!= 0 && !is_header
) {
146 putc('\n', fo
), sz
++;
152 * Decode from base64.
155 mime_fromb64(struct str
*in
, struct str
*out
, int is_text
)
158 signed char c
, d
, e
, f
, g
;
159 int done
= 0, newline
= 0;
161 out
->s
= smalloc(in
->l
* 3 / 4 + 2);
163 upper
= in
->s
+ in
->l
;
164 for (p
= in
->s
, q
= out
->s
; p
< upper
; ) {
165 while (c
= *p
++, whitechar(c
));
166 if (p
>= upper
) break;
168 while (d
= *p
++, whitechar(d
));
169 if (p
>= upper
) break;
170 while (e
= *p
++, whitechar(e
));
171 if (p
>= upper
) break;
172 while (f
= *p
++, whitechar(f
));
173 if (c
== '=' || d
== '=') {
179 g
= ((c
<< 2) | ((d
& 0x30) >> 4));
183 } else if (g
== '\n' && newline
) {
197 g
= (((d
& 0xF) << 4) | ((e
& 0x3C) >> 2));
201 } else if (g
== '\n' && newline
) {
215 g
= (((e
& 0x03) << 6) | f
);
219 } else if (g
== '\n' && newline
) {
236 * Buffer the base64 input so mime_fromb64 gets always multiples of
238 * As we have only one buffer, this function is not reentrant.
241 mime_fromb64_b(struct str
*in
, struct str
*out
, int is_text
, FILE *f
)
243 static signed char b
[4];
245 static FILE *f_b
= (FILE *)-1;
250 nin
.s
= smalloc(in
->l
+ n
);
251 if (n
!= 0 && f_b
== f
) {
252 for (nin
.l
= 0; nin
.l
< n
; nin
.l
++)
253 nin
.s
[nin
.l
] = b
[nin
.l
];
259 for (i
= 0; i
<= in
->l
; i
++) {
261 if (char64(c
) == -1 && c
!= '=')
263 b
[n
] = nin
.s
[nin
.l
++] = c
;
270 mime_fromb64(&nin
, out
, is_text
);