1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter/* base64 encoder/decoder. Originally part of main/util.c
18251876Speter * but moved here so that support/ab and apr_sha1.c could
19251876Speter * use it. This meant removing the apr_palloc()s and adding
20251876Speter * ugly 'len' functions, which is quite a nasty cost.
21251876Speter */
22251876Speter
23251876Speter#include "apr_base64.h"
24251876Speter#if APR_CHARSET_EBCDIC
25251876Speter#include "apr_xlate.h"
26251876Speter#endif				/* APR_CHARSET_EBCDIC */
27251876Speter
28251876Speter/* aaaack but it's fast and const should make it shared text page. */
29251876Speterstatic const unsigned char pr2six[256] =
30251876Speter{
31251876Speter#if !APR_CHARSET_EBCDIC
32251876Speter    /* ASCII table */
33251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
35251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
36251876Speter    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
37251876Speter    64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
38251876Speter    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
39251876Speter    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
40251876Speter    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
41251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
42251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
43251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
44251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
45251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
46251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
47251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
48251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
49251876Speter#else /*APR_CHARSET_EBCDIC*/
50251876Speter    /* EBCDIC table */
51251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
52251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
53251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
54251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
55251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
56251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
57251876Speter    64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
58251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
59251876Speter    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
60251876Speter    64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
61251876Speter    64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
62251876Speter    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
63251876Speter    64,  0,  1,  2,  3,  4,  5,  6,  7,  8, 64, 64, 64, 64, 64, 64,
64251876Speter    64,  9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
65251876Speter    64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
66251876Speter    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
67251876Speter#endif /*APR_CHARSET_EBCDIC*/
68251876Speter};
69251876Speter
70251876Speter#if APR_CHARSET_EBCDIC
71251876Speterstatic apr_xlate_t *xlate_to_ebcdic;
72251876Speterstatic unsigned char os_toascii[256];
73251876Speter
74251876SpeterAPU_DECLARE(apr_status_t) apr_base64init_ebcdic(apr_xlate_t *to_ascii,
75251876Speter                                             apr_xlate_t *to_ebcdic)
76251876Speter{
77251876Speter    int i;
78251876Speter    apr_size_t inbytes_left, outbytes_left;
79251876Speter    apr_status_t rv;
80251876Speter    int onoff;
81251876Speter
82251876Speter    /* Only single-byte conversion is supported.
83251876Speter     */
84251876Speter    rv = apr_xlate_sb_get(to_ascii, &onoff);
85251876Speter    if (rv) {
86251876Speter        return rv;
87251876Speter    }
88251876Speter    if (!onoff) { /* If conversion is not single-byte-only */
89251876Speter        return APR_EINVAL;
90251876Speter    }
91251876Speter    rv = apr_xlate_sb_get(to_ebcdic, &onoff);
92251876Speter    if (rv) {
93251876Speter        return rv;
94251876Speter    }
95251876Speter    if (!onoff) { /* If conversion is not single-byte-only */
96251876Speter        return APR_EINVAL;
97251876Speter    }
98251876Speter    xlate_to_ebcdic = to_ebcdic;
99251876Speter    for (i = 0; i < sizeof(os_toascii); i++) {
100251876Speter        os_toascii[i] = i;
101251876Speter    }
102251876Speter    inbytes_left = outbytes_left = sizeof(os_toascii);
103251876Speter    apr_xlate_conv_buffer(to_ascii, os_toascii, &inbytes_left,
104251876Speter                          os_toascii, &outbytes_left);
105251876Speter
106251876Speter    return APR_SUCCESS;
107251876Speter}
108251876Speter#endif /*APR_CHARSET_EBCDIC*/
109251876Speter
110251876SpeterAPU_DECLARE(int) apr_base64_decode_len(const char *bufcoded)
111251876Speter{
112251876Speter    int nbytesdecoded;
113251876Speter    register const unsigned char *bufin;
114251876Speter    register apr_size_t nprbytes;
115251876Speter
116251876Speter    bufin = (const unsigned char *) bufcoded;
117251876Speter    while (pr2six[*(bufin++)] <= 63);
118251876Speter
119251876Speter    nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
120251876Speter    nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
121251876Speter
122251876Speter    return nbytesdecoded + 1;
123251876Speter}
124251876Speter
125251876SpeterAPU_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded)
126251876Speter{
127251876Speter#if APR_CHARSET_EBCDIC
128251876Speter    apr_size_t inbytes_left, outbytes_left;
129251876Speter#endif				/* APR_CHARSET_EBCDIC */
130251876Speter    int len;
131251876Speter
132251876Speter    len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded);
133251876Speter#if APR_CHARSET_EBCDIC
134251876Speter    inbytes_left = outbytes_left = len;
135251876Speter    apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left,
136251876Speter                          bufplain, &outbytes_left);
137251876Speter#endif				/* APR_CHARSET_EBCDIC */
138251876Speter    bufplain[len] = '\0';
139251876Speter    return len;
140251876Speter}
141251876Speter
142251876Speter/* This is the same as apr_base64_decode() except on EBCDIC machines, where
143251876Speter * the conversion of the output to ebcdic is left out.
144251876Speter */
145251876SpeterAPU_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain,
146251876Speter				   const char *bufcoded)
147251876Speter{
148251876Speter    int nbytesdecoded;
149251876Speter    register const unsigned char *bufin;
150251876Speter    register unsigned char *bufout;
151251876Speter    register apr_size_t nprbytes;
152251876Speter
153251876Speter    bufin = (const unsigned char *) bufcoded;
154251876Speter    while (pr2six[*(bufin++)] <= 63);
155251876Speter    nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
156251876Speter    nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
157251876Speter
158251876Speter    bufout = (unsigned char *) bufplain;
159251876Speter    bufin = (const unsigned char *) bufcoded;
160251876Speter
161251876Speter    while (nprbytes > 4) {
162251876Speter	*(bufout++) =
163251876Speter	    (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
164251876Speter	*(bufout++) =
165251876Speter	    (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
166251876Speter	*(bufout++) =
167251876Speter	    (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
168251876Speter	bufin += 4;
169251876Speter	nprbytes -= 4;
170251876Speter    }
171251876Speter
172251876Speter    /* Note: (nprbytes == 1) would be an error, so just ingore that case */
173251876Speter    if (nprbytes > 1) {
174251876Speter	*(bufout++) =
175251876Speter	    (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
176251876Speter    }
177251876Speter    if (nprbytes > 2) {
178251876Speter	*(bufout++) =
179251876Speter	    (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
180251876Speter    }
181251876Speter    if (nprbytes > 3) {
182251876Speter	*(bufout++) =
183251876Speter	    (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
184251876Speter    }
185251876Speter
186251876Speter    nbytesdecoded -= (4 - (int)nprbytes) & 3;
187251876Speter    return nbytesdecoded;
188251876Speter}
189251876Speter
190251876Speterstatic const char basis_64[] =
191251876Speter    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
192251876Speter
193251876SpeterAPU_DECLARE(int) apr_base64_encode_len(int len)
194251876Speter{
195251876Speter    return ((len + 2) / 3 * 4) + 1;
196251876Speter}
197251876Speter
198251876SpeterAPU_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len)
199251876Speter{
200251876Speter#if !APR_CHARSET_EBCDIC
201251876Speter    return apr_base64_encode_binary(encoded, (const unsigned char *) string, len);
202251876Speter#else /* APR_CHARSET_EBCDIC */
203251876Speter    int i;
204251876Speter    char *p;
205251876Speter
206251876Speter    p = encoded;
207251876Speter    for (i = 0; i < len - 2; i += 3) {
208251876Speter	*p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
209251876Speter	*p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
210251876Speter	                ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
211251876Speter	*p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
212251876Speter	                ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
213251876Speter	*p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
214251876Speter    }
215251876Speter    if (i < len) {
216251876Speter	*p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
217251876Speter	if (i == (len - 1)) {
218251876Speter	    *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
219251876Speter	    *p++ = '=';
220251876Speter	}
221251876Speter	else {
222251876Speter	    *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
223251876Speter	                    ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
224251876Speter	    *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
225251876Speter	}
226251876Speter	*p++ = '=';
227251876Speter    }
228251876Speter
229251876Speter    *p++ = '\0';
230251876Speter    return p - encoded;
231251876Speter#endif				/* APR_CHARSET_EBCDIC */
232251876Speter}
233251876Speter
234251876Speter/* This is the same as apr_base64_encode() except on EBCDIC machines, where
235251876Speter * the conversion of the input to ascii is left out.
236251876Speter */
237251876SpeterAPU_DECLARE(int) apr_base64_encode_binary(char *encoded,
238251876Speter                                      const unsigned char *string, int len)
239251876Speter{
240251876Speter    int i;
241251876Speter    char *p;
242251876Speter
243251876Speter    p = encoded;
244251876Speter    for (i = 0; i < len - 2; i += 3) {
245251876Speter	*p++ = basis_64[(string[i] >> 2) & 0x3F];
246251876Speter	*p++ = basis_64[((string[i] & 0x3) << 4) |
247251876Speter	                ((int) (string[i + 1] & 0xF0) >> 4)];
248251876Speter	*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
249251876Speter	                ((int) (string[i + 2] & 0xC0) >> 6)];
250251876Speter	*p++ = basis_64[string[i + 2] & 0x3F];
251251876Speter    }
252251876Speter    if (i < len) {
253251876Speter	*p++ = basis_64[(string[i] >> 2) & 0x3F];
254251876Speter	if (i == (len - 1)) {
255251876Speter	    *p++ = basis_64[((string[i] & 0x3) << 4)];
256251876Speter	    *p++ = '=';
257251876Speter	}
258251876Speter	else {
259251876Speter	    *p++ = basis_64[((string[i] & 0x3) << 4) |
260251876Speter	                    ((int) (string[i + 1] & 0xF0) >> 4)];
261251876Speter	    *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
262251876Speter	}
263251876Speter	*p++ = '=';
264251876Speter    }
265251876Speter
266251876Speter    *p++ = '\0';
267251876Speter    return (int)(p - encoded);
268251876Speter}
269