1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 /* base64 encoder/decoder. Originally part of main/util.c
18 * but moved here so that support/ab and apr_sha1.c could
19 * use it. This meant removing the apr_palloc()s and adding
20 * ugly 'len' functions, which is quite a nasty cost.
23 #include "apr_base64.h"
24 #if APR_CHARSET_EBCDIC
25 #include "apr_xlate.h"
26 #endif /* APR_CHARSET_EBCDIC */
28 /* aaaack but it's fast and const should make it shared text page. */
29 static const unsigned char pr2six[256] =
31 #if !APR_CHARSET_EBCDIC
33 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
35 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
36 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
37 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
38 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
39 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
40 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
41 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
42 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
43 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
44 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
45 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
46 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
47 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
48 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
49 #else /*APR_CHARSET_EBCDIC*/
51 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
52 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
53 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
54 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
55 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
56 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
57 64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
58 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
59 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
60 64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
61 64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
62 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
63 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 64, 64, 64, 64, 64, 64,
64 64, 9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
65 64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
66 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
67 #endif /*APR_CHARSET_EBCDIC*/
70 #if APR_CHARSET_EBCDIC
71 static apr_xlate_t *xlate_to_ebcdic;
72 static unsigned char os_toascii[256];
74 APU_DECLARE(apr_status_t) apr_base64init_ebcdic(apr_xlate_t *to_ascii,
75 apr_xlate_t *to_ebcdic)
78 apr_size_t inbytes_left, outbytes_left;
82 /* Only single-byte conversion is supported.
84 rv = apr_xlate_sb_get(to_ascii, &onoff);
88 if (!onoff) { /* If conversion is not single-byte-only */
91 rv = apr_xlate_sb_get(to_ebcdic, &onoff);
95 if (!onoff) { /* If conversion is not single-byte-only */
98 xlate_to_ebcdic = to_ebcdic;
99 for (i = 0; i < sizeof(os_toascii); i++) {
102 inbytes_left = outbytes_left = sizeof(os_toascii);
103 apr_xlate_conv_buffer(to_ascii, os_toascii, &inbytes_left,
104 os_toascii, &outbytes_left);
108 #endif /*APR_CHARSET_EBCDIC*/
110 APU_DECLARE(int) apr_base64_decode_len(const char *bufcoded)
113 register const unsigned char *bufin;
114 register apr_size_t nprbytes;
116 bufin = (const unsigned char *) bufcoded;
117 while (pr2six[*(bufin++)] <= 63);
119 nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
120 nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
122 return nbytesdecoded + 1;
125 APU_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded)
127 #if APR_CHARSET_EBCDIC
128 apr_size_t inbytes_left, outbytes_left;
129 #endif /* APR_CHARSET_EBCDIC */
132 len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded);
133 #if APR_CHARSET_EBCDIC
134 inbytes_left = outbytes_left = len;
135 apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left,
136 bufplain, &outbytes_left);
137 #endif /* APR_CHARSET_EBCDIC */
138 bufplain[len] = '\0';
142 /* This is the same as apr_base64_decode() except on EBCDIC machines, where
143 * the conversion of the output to ebcdic is left out.
145 APU_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain,
146 const char *bufcoded)
149 register const unsigned char *bufin;
150 register unsigned char *bufout;
151 register apr_size_t nprbytes;
153 bufin = (const unsigned char *) bufcoded;
154 while (pr2six[*(bufin++)] <= 63);
155 nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
156 nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
158 bufout = (unsigned char *) bufplain;
159 bufin = (const unsigned char *) bufcoded;
161 while (nprbytes > 4) {
163 (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
165 (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
167 (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
172 /* Note: (nprbytes == 1) would be an error, so just ingore that case */
175 (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
179 (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
183 (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
186 nbytesdecoded -= (4 - (int)nprbytes) & 3;
187 return nbytesdecoded;
190 static const char basis_64[] =
191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
193 APU_DECLARE(int) apr_base64_encode_len(int len)
195 return ((len + 2) / 3 * 4) + 1;
198 APU_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len)
200 #if !APR_CHARSET_EBCDIC
201 return apr_base64_encode_binary(encoded, (const unsigned char *) string, len);
202 #else /* APR_CHARSET_EBCDIC */
207 for (i = 0; i < len - 2; i += 3) {
208 *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
209 *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
210 ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
211 *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
212 ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
213 *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
216 *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
217 if (i == (len - 1)) {
218 *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
222 *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
223 ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
224 *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
231 #endif /* APR_CHARSET_EBCDIC */
234 /* This is the same as apr_base64_encode() except on EBCDIC machines, where
235 * the conversion of the input to ascii is left out.
237 APU_DECLARE(int) apr_base64_encode_binary(char *encoded,
238 const unsigned char *string, int len)
244 for (i = 0; i < len - 2; i += 3) {
245 *p++ = basis_64[(string[i] >> 2) & 0x3F];
246 *p++ = basis_64[((string[i] & 0x3) << 4) |
247 ((int) (string[i + 1] & 0xF0) >> 4)];
248 *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
249 ((int) (string[i + 2] & 0xC0) >> 6)];
250 *p++ = basis_64[string[i + 2] & 0x3F];
253 *p++ = basis_64[(string[i] >> 2) & 0x3F];
254 if (i == (len - 1)) {
255 *p++ = basis_64[((string[i] & 0x3) << 4)];
259 *p++ = basis_64[((string[i] & 0x3) << 4) |
260 ((int) (string[i + 1] & 0xF0) >> 4)];
261 *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
267 return (int)(p - encoded);