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
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/* encode/decode functions.
18 *
19 * These functions perform various encoding operations, and are provided in
20 * pairs, a function to query the length of and encode existing buffers, as
21 * well as companion functions to perform the same process to memory
22 * allocated from a pool.
23 *
24 * The API is designed to have the smallest possible RAM footprint, and so
25 * will only allocate the exact amount of RAM needed for each conversion.
26 */
27
28#include "apr_encode.h"
29#include "apr_lib.h"
30#include "apr_strings.h"
31#include "apr_encode_private.h"
32
33/* lookup table: fast and const should make it shared text page. */
34static const unsigned char pr2six[256] =
35{
36#if !APR_CHARSET_EBCDIC
37    /* ASCII table */
38    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
39    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
40    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 62, 64, 63,
41    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 128, 64, 64,
42    64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
43    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 63,
44    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
45    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 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    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
50    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
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#else                           /* APR_CHARSET_EBCDIC */
55    /* EBCDIC table */
56    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
57    64, 64, 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, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
60    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
61    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
62    62, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63, 64, 64,
63    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64,
64    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
65    64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
66    64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
67    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
68    64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 64, 64, 64, 64, 64, 64,
69    64, 9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
70    64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
71    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
72#endif                          /* APR_CHARSET_EBCDIC */
73};
74
75static const unsigned char pr2five[256] =
76{
77#if !APR_CHARSET_EBCDIC
78    /* ASCII table */
79    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
80    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
81    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
82    32, 32, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 128, 32, 32,
83    32, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
84    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, 32, 32, 32, 32,
85    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
86    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
87    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
88    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
89    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
90    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
91    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
92    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
93    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
94    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
95#else                           /* APR_CHARSET_EBCDIC */
96    /* EBCDIC table */
97    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
98    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
99    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
100    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
101    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
102    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
103    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
104    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 128, 32,
105    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
106    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
107    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
108    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
109    32, 0, 1, 2, 3, 4, 5, 6, 7, 8, 32, 32, 32, 32, 32, 32,
110    32, 9, 10, 11, 12, 13, 14, 15, 16, 17, 32, 32, 32, 32, 32, 32,
111    32, 32, 18, 19, 20, 21, 22, 23, 24, 25, 32, 32, 32, 32, 32, 32,
112    32, 32, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 32, 32
113#endif                          /* APR_CHARSET_EBCDIC */
114};
115
116static const unsigned char pr2fivehex[256] =
117{
118#if !APR_CHARSET_EBCDIC
119    /* ASCII table */
120    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
121    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
122    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
123    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 32, 32, 32, 128, 32, 32,
124    32, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
125    25, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32,
126    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
127    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
128    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
129    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
130    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
131    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
132    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
133    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
134    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
135    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
136#else                           /* APR_CHARSET_EBCDIC */
137    /* EBCDIC table */
138    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
139    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
140    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
141    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
142    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
143    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
144    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
145    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 128, 32,
146    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
147    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
148    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
149    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
150    32, 10, 11, 12, 13, 14, 15, 16, 17, 18, 32, 32, 32, 32, 32, 32,
151    32, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 32, 32, 32, 32, 32,
152    32, 32, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
153    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 32, 32, 32, 32, 32, 32
154#endif                          /* APR_CHARSET_EBCDIC */
155};
156
157static const unsigned char pr2two[256] =
158{
159#if !APR_CHARSET_EBCDIC
160    /* ASCII table */
161    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
162    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
163    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
164    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 32, 16, 16, 16, 16, 16,
165    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
166    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
167    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
168    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
169    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
170    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
171    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
172    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
173    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
174    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
175    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
176    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
177#else                           /* APR_CHARSET_EBCDIC */
178    /* EBCDIC table */
179    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
180    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
181    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
182    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
183    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
184    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
185    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
186    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 16, 16, 16, 16, 16,
187    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
188    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
189    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
190    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
191    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
192    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
193    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
194    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 16, 16, 16, 16, 16
195#endif                          /* APR_CHARSET_EBCDIC */
196};
197
198static const char base64[] =
199"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
200static const char base64url[] =
201"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
202
203static const char base32[] =
204"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
205static const char base32hex[] =
206"0123456789ABCDEFGHIJKLMNOPQRSTUV";
207
208static const char base16[] = "0123456789ABCDEF";
209static const char base16lower[] = "0123456789abcdef";
210
211APR_DECLARE(apr_status_t) apr_encode_base64(char *dest, const char *src,
212                              apr_ssize_t slen, int flags, apr_size_t * len)
213{
214    const char *base;
215
216    if (!src) {
217        return APR_NOTFOUND;
218    }
219
220    if (APR_ENCODE_STRING == slen) {
221        slen = strlen(src);
222    }
223
224    if (dest) {
225        register char *bufout = dest;
226        int i;
227
228        if (0 == ((flags & APR_ENCODE_BASE64URL))) {
229            base = base64;
230        }
231        else {
232            base = base64url;
233        }
234
235        for (i = 0; i < slen - 2; i += 3) {
236            *bufout++ = base[ENCODE_TO_ASCII(((src[i]) >> 2) & 0x3F)];
237            *bufout++ = base[ENCODE_TO_ASCII((((src[i]) & 0x3) << 4)
238                                      | ((int)((src[i + 1]) & 0xF0) >> 4))];
239            *bufout++ = base[ENCODE_TO_ASCII((((src[i + 1]) & 0xF) << 2)
240                       | ((int)(ENCODE_TO_ASCII(src[i + 2]) & 0xC0) >> 6))];
241            *bufout++ = base[ENCODE_TO_ASCII((src[i + 2]) & 0x3F)];
242        }
243        if (i < slen) {
244            *bufout++ = base[ENCODE_TO_ASCII(((src[i]) >> 2) & 0x3F)];
245            if (i == (slen - 1)) {
246                *bufout++ = base[ENCODE_TO_ASCII((((src[i]) & 0x3) << 4))];
247                if (!(flags & APR_ENCODE_NOPADDING)) {
248                    *bufout++ = '=';
249                }
250            }
251            else {
252                *bufout++ = base[ENCODE_TO_ASCII((((src[i]) & 0x3) << 4)
253                                      | ((int)((src[i + 1]) & 0xF0) >> 4))];
254                *bufout++ = base[ENCODE_TO_ASCII(((src[i + 1]) & 0xF) << 2)];
255            }
256            if (!(flags & APR_ENCODE_NOPADDING)) {
257                *bufout++ = '=';
258            }
259        }
260
261        if (len) {
262            *len = bufout - dest;
263        }
264
265        *bufout++ = '\0';
266
267        return APR_SUCCESS;
268    }
269
270    if (len) {
271        *len = ((slen + 2) / 3 * 4) + 1;
272    }
273
274    return APR_SUCCESS;
275}
276
277APR_DECLARE(apr_status_t) apr_encode_base64_binary(char *dest, const unsigned char *src,
278                              apr_ssize_t slen, int flags, apr_size_t * len)
279{
280    const char *base;
281
282    if (!src) {
283        return APR_NOTFOUND;
284    }
285
286    if (dest) {
287        register char *bufout = dest;
288        int i;
289
290        if (0 == ((flags & APR_ENCODE_BASE64URL))) {
291            base = base64;
292        }
293        else {
294            base = base64url;
295        }
296
297        for (i = 0; i < slen - 2; i += 3) {
298            *bufout++ = base[(src[i] >> 2) & 0x3F];
299            *bufout++ = base[((src[i] & 0x3) << 4)
300                             | ((int)(src[i + 1] & 0xF0) >> 4)];
301            *bufout++ = base[((src[i + 1] & 0xF) << 2)
302                             | ((int)(src[i + 2] & 0xC0) >> 6)];
303            *bufout++ = base[src[i + 2] & 0x3F];
304        }
305        if (i < slen) {
306            *bufout++ = base[(src[i] >> 2) & 0x3F];
307            if (i == (slen - 1)) {
308                *bufout++ = base[((src[i] & 0x3) << 4)];
309                if (!(flags & APR_ENCODE_NOPADDING)) {
310                    *bufout++ = '=';
311                }
312            }
313            else {
314                *bufout++ = base[((src[i] & 0x3) << 4)
315                                 | ((int)(src[i + 1] & 0xF0) >> 4)];
316                *bufout++ = base[((src[i + 1] & 0xF) << 2)];
317            }
318            if (!(flags & APR_ENCODE_NOPADDING)) {
319                *bufout++ = '=';
320            }
321        }
322
323        if (len) {
324            *len = bufout - dest;
325        }
326
327        *bufout++ = '\0';
328
329        return APR_SUCCESS;
330    }
331
332    if (len) {
333        *len = ((slen + 2) / 3 * 4) + 1;
334    }
335
336    return APR_SUCCESS;
337}
338
339APR_DECLARE(const char *)apr_pencode_base64(apr_pool_t * p, const char *src,
340                              apr_ssize_t slen, int flags, apr_size_t * len)
341{
342    apr_size_t size;
343
344    switch (apr_encode_base64(NULL, src, slen, flags, &size)) {
345    case APR_SUCCESS:{
346            char *cmd = apr_palloc(p, size);
347            apr_encode_base64(cmd, src, slen, flags, len);
348            return cmd;
349        }
350    case APR_NOTFOUND:{
351            break;
352        }
353    }
354
355    return NULL;
356}
357
358APR_DECLARE(const char *)apr_pencode_base64_binary(apr_pool_t * p, const unsigned char *src,
359                              apr_ssize_t slen, int flags, apr_size_t * len)
360{
361    apr_size_t size;
362
363    switch (apr_encode_base64_binary(NULL, src, slen, flags, &size)) {
364    case APR_SUCCESS:{
365            char *cmd = apr_palloc(p, size);
366            apr_encode_base64_binary(cmd, src, slen, flags, len);
367            return cmd;
368        }
369    case APR_NOTFOUND:{
370            break;
371        }
372    }
373
374    return NULL;
375}
376
377APR_DECLARE(apr_status_t) apr_decode_base64(char *dest, const char *src,
378                              apr_ssize_t slen, int flags, apr_size_t * len)
379{
380    if (!src) {
381        return APR_NOTFOUND;
382    }
383
384    if (APR_ENCODE_STRING == slen) {
385        slen = strlen(src);
386    }
387
388    if (dest) {
389        register const unsigned char *bufin;
390        register unsigned char *bufout;
391        register apr_size_t nprbytes;
392        register apr_size_t count = slen;
393
394        apr_status_t status;
395
396        bufin = (const unsigned char *)src;
397        while (pr2six[*(bufin++)] < 64 && count)
398            count--;
399        nprbytes = (bufin - (const unsigned char *)src) - 1;
400        while (pr2six[*(bufin++)] > 64 && count)
401            count--;
402
403        status = flags & APR_ENCODE_RELAXED ? APR_SUCCESS :
404            count ? APR_BADCH : APR_SUCCESS;
405
406        bufout = (unsigned char *)dest;
407        bufin = (const unsigned char *)src;
408
409        while (nprbytes > 4) {
410            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2six[bufin[0]] << 2
411                                                   | pr2six[bufin[1]] >> 4);
412            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
413                             pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
414            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
415                                  pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
416            bufin += 4;
417            nprbytes -= 4;
418        }
419
420        if (nprbytes == 1) {
421            status = APR_BADCH;
422        }
423        if (nprbytes > 1) {
424            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
425                               pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
426        }
427        if (nprbytes > 2) {
428            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
429                             pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
430        }
431        if (nprbytes > 3) {
432            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
433                                  pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
434        }
435
436        if (len) {
437            *len = bufout - (unsigned char *)dest;
438        }
439
440        *(bufout++) = 0;
441
442        return status;
443    }
444
445    if (len) {
446        *len = (((int)slen + 3) / 4) * 3 + 1;
447    }
448
449    return APR_SUCCESS;
450}
451
452APR_DECLARE(apr_status_t) apr_decode_base64_binary(unsigned char *dest,
453             const char *src, apr_ssize_t slen, int flags, apr_size_t * len)
454{
455    if (!src) {
456        return APR_NOTFOUND;
457    }
458
459    if (APR_ENCODE_STRING == slen) {
460        slen = strlen(src);
461    }
462
463    if (dest) {
464        register const unsigned char *bufin;
465        register unsigned char *bufout;
466        register apr_size_t nprbytes;
467        register apr_size_t count = slen;
468
469        apr_status_t status;
470
471        bufin = (const unsigned char *)src;
472        while (pr2six[*(bufin++)] < 64 && count)
473            count--;
474        nprbytes = (bufin - (const unsigned char *)src) - 1;
475        while (pr2six[*(bufin++)] > 64 && count)
476            count--;
477
478        status = flags & APR_ENCODE_RELAXED ? APR_SUCCESS :
479            count ? APR_BADCH : APR_SUCCESS;
480
481        bufout = (unsigned char *)dest;
482        bufin = (const unsigned char *)src;
483
484        while (nprbytes > 4) {
485            *(bufout++) = (unsigned char)(pr2six[bufin[0]] << 2
486                                          | pr2six[bufin[1]] >> 4);
487            *(bufout++) = (unsigned char)(pr2six[bufin[1]] << 4
488                                          | pr2six[bufin[2]] >> 2);
489            *(bufout++) = (unsigned char)(pr2six[bufin[2]] << 6
490                                          | pr2six[bufin[3]]);
491            bufin += 4;
492            nprbytes -= 4;
493        }
494
495        if (nprbytes == 1) {
496            status = APR_BADCH;
497        }
498        if (nprbytes > 1) {
499            *(bufout++) = (unsigned char)(pr2six[bufin[0]] << 2
500                                          | pr2six[bufin[1]] >> 4);
501        }
502        if (nprbytes > 2) {
503            *(bufout++) = (unsigned char)(pr2six[bufin[1]] << 4
504                                          | pr2six[bufin[2]] >> 2);
505        }
506        if (nprbytes > 3) {
507            *(bufout++) = (unsigned char)(pr2six[bufin[2]] << 6
508                                          | pr2six[bufin[3]]);
509        }
510
511        if (len) {
512            *len = bufout - dest;
513        }
514
515        return status;
516    }
517
518    if (len) {
519        *len = (((int)slen + 3) / 4) * 3;
520    }
521
522    return APR_SUCCESS;
523}
524
525APR_DECLARE(const char *)apr_pdecode_base64(apr_pool_t * p, const char *str,
526                              apr_ssize_t slen, int flags, apr_size_t * len)
527{
528    apr_size_t size;
529
530    switch (apr_decode_base64(NULL, str, slen, flags, &size)) {
531    case APR_SUCCESS:{
532            void *cmd = apr_palloc(p, size);
533            apr_decode_base64(cmd, str, slen, flags, len);
534            return cmd;
535        }
536    case APR_BADCH:
537    case APR_NOTFOUND:{
538            break;
539        }
540    }
541
542    return NULL;
543}
544
545APR_DECLARE(const unsigned char *)apr_pdecode_base64_binary(apr_pool_t * p,
546             const char *str, apr_ssize_t slen, int flags, apr_size_t * len)
547{
548    apr_size_t size;
549
550    switch (apr_decode_base64_binary(NULL, str, slen, flags, &size)) {
551    case APR_SUCCESS:{
552            unsigned char *cmd = apr_palloc(p, size + 1);
553            cmd[size] = 0;
554            apr_decode_base64_binary(cmd, str, slen, flags, len);
555            return cmd;
556        }
557    case APR_BADCH:
558    case APR_NOTFOUND:{
559            break;
560        }
561    }
562
563    return NULL;
564}
565
566APR_DECLARE(apr_status_t) apr_encode_base32(char *dest, const char *src,
567                              apr_ssize_t slen, int flags, apr_size_t * len)
568{
569    const char *base;
570
571    if (!src) {
572        return APR_NOTFOUND;
573    }
574
575    if (APR_ENCODE_STRING == slen) {
576        slen = strlen(src);
577    }
578
579    if (dest) {
580        register char *bufout = dest;
581        int i;
582
583        if (!((flags & APR_ENCODE_BASE32HEX))) {
584            base = base32;
585        }
586        else {
587            base = base32hex;
588        }
589
590        for (i = 0; i < slen - 4; i += 5) {
591            *bufout++ = base[ENCODE_TO_ASCII((src[i] >> 3) & 0x1F)];
592            *bufout++ = base[ENCODE_TO_ASCII(((src[i] << 2) & 0x1C)
593                                             | ((src[i + 1] >> 6) & 0x3))];
594            *bufout++ = base[ENCODE_TO_ASCII((src[i + 1] >> 1) & 0x1F)];
595            *bufout++ = base[ENCODE_TO_ASCII(((src[i + 1] << 4) & 0x10)
596                                             | ((src[i + 2] >> 4) & 0xF))];
597            *bufout++ = base[ENCODE_TO_ASCII(((src[i + 2] << 1) & 0x1E)
598                                             | ((src[i + 3] >> 7) & 0x1))];
599            *bufout++ = base[ENCODE_TO_ASCII((src[i + 3] >> 2) & 0x1F)];
600            *bufout++ = base[ENCODE_TO_ASCII(((src[i + 3] << 3) & 0x18)
601                                             | ((src[i + 4] >> 5) & 0x7))];
602            *bufout++ = base[ENCODE_TO_ASCII(src[i + 4] & 0x1F)];
603        }
604        if (i < slen) {
605            *bufout++ = base[ENCODE_TO_ASCII(src[i] >> 3) & 0x1F];
606            if (i == (slen - 1)) {
607                *bufout++ = base[ENCODE_TO_ASCII((src[i] << 2) & 0x1C)];
608                if (!(flags & APR_ENCODE_NOPADDING)) {
609                    *bufout++ = '=';
610                    *bufout++ = '=';
611                    *bufout++ = '=';
612                    *bufout++ = '=';
613                    *bufout++ = '=';
614                    *bufout++ = '=';
615                }
616            }
617            else if (i == (slen - 2)) {
618                *bufout++ = base[ENCODE_TO_ASCII(((src[i] << 2) & 0x1C)
619                                              | ((src[i + 1] >> 6) & 0x3))];
620                *bufout++ = base[ENCODE_TO_ASCII((src[i + 1] >> 1) & 0x1F)];
621                *bufout++ = base[ENCODE_TO_ASCII((src[i + 1] << 4) & 0x10)];
622                if (!(flags & APR_ENCODE_NOPADDING)) {
623                    *bufout++ = '=';
624                    *bufout++ = '=';
625                    *bufout++ = '=';
626                    *bufout++ = '=';
627                }
628            }
629            else if (i == (slen - 3)) {
630                *bufout++ = base[ENCODE_TO_ASCII(((src[i] << 2) & 0x1C)
631                                              | ((src[i + 1] >> 6) & 0x3))];
632                *bufout++ = base[ENCODE_TO_ASCII((src[i + 1] >> 1) & 0x1F)];
633                *bufout++ = base[ENCODE_TO_ASCII(((src[i + 1] << 4) & 0x10)
634                                              | ((src[i + 2] >> 4) & 0xF))];
635                *bufout++ = base[ENCODE_TO_ASCII((src[i + 2] << 1) & 0x1E)];
636                if (!(flags & APR_ENCODE_NOPADDING)) {
637                    *bufout++ = '=';
638                    *bufout++ = '=';
639                    *bufout++ = '=';
640                }
641            }
642            else {
643                *bufout++ = base[ENCODE_TO_ASCII(((src[i] << 2) & 0x1C)
644                                              | ((src[i + 1] >> 6) & 0x3))];
645                *bufout++ = base[ENCODE_TO_ASCII((src[i + 1] >> 1) & 0x1F)];
646                *bufout++ = base[ENCODE_TO_ASCII(((src[i + 1] << 4) & 0x10)
647                                              | ((src[i + 2] >> 4) & 0xF))];
648                *bufout++ = base[ENCODE_TO_ASCII(((src[i + 2] << 1) & 0x1E)
649                                              | ((src[i + 3] >> 7) & 0x1))];
650                *bufout++ = base[ENCODE_TO_ASCII((src[i + 3] >> 2) & 0x1F)];
651                *bufout++ = base[ENCODE_TO_ASCII((src[i + 3] << 3) & 0x18)];
652                if (!(flags & APR_ENCODE_NOPADDING)) {
653                    *bufout++ = '=';
654                }
655            }
656        }
657
658        if (len) {
659            *len = bufout - dest;
660        }
661
662        *bufout++ = '\0';
663
664        return APR_SUCCESS;
665    }
666
667    if (len) {
668        *len = ((slen + 2) / 3 * 4) + 1;
669    }
670
671    return APR_SUCCESS;
672}
673
674APR_DECLARE(apr_status_t) apr_encode_base32_binary(char *dest, const unsigned char *src,
675                              apr_ssize_t slen, int flags, apr_size_t * len)
676{
677    const char *base;
678
679    if (!src) {
680        return APR_NOTFOUND;
681    }
682
683    if (dest) {
684        register char *bufout = dest;
685        int i;
686
687        if (!((flags & APR_ENCODE_BASE32HEX))) {
688            base = base32;
689        }
690        else {
691            base = base32hex;
692        }
693
694        for (i = 0; i < slen - 4; i += 5) {
695            *bufout++ = base[((src[i] >> 3) & 0x1F)];
696            *bufout++ = base[(((src[i] << 2) & 0x1C)
697                              | ((src[i + 1] >> 6) & 0x3))];
698            *bufout++ = base[((src[i + 1] >> 1) & 0x1F)];
699            *bufout++ = base[(((src[i + 1] << 4) & 0x10)
700                              | ((src[i + 2] >> 4) & 0xF))];
701            *bufout++ = base[(((src[i + 2] << 1) & 0x1E)
702                              | ((src[i + 3] >> 7) & 0x1))];
703            *bufout++ = base[((src[i + 3] >> 2) & 0x1F)];
704            *bufout++ = base[(((src[i + 3] << 3) & 0x18)
705                              | ((src[i + 4] >> 5) & 0x7))];
706            *bufout++ = base[(src[i + 4] & 0x1F)];
707        }
708        if (i < slen) {
709            *bufout++ = base[(src[i] >> 3) & 0x1F];
710            if (i == (slen - 1)) {
711                *bufout++ = base[((src[i] << 2) & 0x1C)];
712                if (!(flags & APR_ENCODE_NOPADDING)) {
713                    *bufout++ = '=';
714                    *bufout++ = '=';
715                    *bufout++ = '=';
716                    *bufout++ = '=';
717                    *bufout++ = '=';
718                    *bufout++ = '=';
719                }
720            }
721            else if (i == (slen - 2)) {
722                *bufout++ = base[(((src[i] << 2) & 0x1C)
723                                  | ((src[i + 1] >> 6) & 0x3))];
724                *bufout++ = base[((src[i + 1] >> 1) & 0x1F)];
725                *bufout++ = base[((src[i + 1] << 4) & 0x10)];
726                if (!(flags & APR_ENCODE_NOPADDING)) {
727                    *bufout++ = '=';
728                    *bufout++ = '=';
729                    *bufout++ = '=';
730                    *bufout++ = '=';
731                }
732            }
733            else if (i == (slen - 3)) {
734                *bufout++ = base[(((src[i] << 2) & 0x1C)
735                                  | ((src[i + 1] >> 6) & 0x3))];
736                *bufout++ = base[((src[i + 1] >> 1) & 0x1F)];
737                *bufout++ = base[(((src[i + 1] << 4) & 0x10)
738                                  | ((int)(src[i + 2] >> 4) & 0xF))];
739                *bufout++ = base[((src[i + 2] << 1) & 0x1E)];
740                if (!(flags & APR_ENCODE_NOPADDING)) {
741                    *bufout++ = '=';
742                    *bufout++ = '=';
743                    *bufout++ = '=';
744                }
745            }
746            else {
747                *bufout++ = base[(((src[i] << 2) & 0x1C)
748                                  | ((src[i + 1] >> 6) & 0x3))];
749                *bufout++ = base[((src[i + 1] >> 1) & 0x1F)];
750                *bufout++ = base[(((src[i + 1] << 4) & 0x10)
751                                  | ((src[i + 2] >> 4) & 0xF))];
752                *bufout++ = base[(((src[i + 2] << 1) & 0x1E)
753                                  | ((src[i + 3] >> 7) & 0x1))];
754                *bufout++ = base[((src[i + 3] >> 2) & 0x1F)];
755                *bufout++ = base[((src[i + 3] << 3) & 0x18)];
756                if (!(flags & APR_ENCODE_NOPADDING)) {
757                    *bufout++ = '=';
758                }
759            }
760        }
761
762        if (len) {
763            *len = bufout - dest;
764        }
765
766        *bufout++ = '\0';
767
768        return APR_SUCCESS;
769    }
770
771    if (len) {
772        *len = ((slen + 4) / 5 * 8) + 1;
773    }
774
775    return APR_SUCCESS;
776}
777
778APR_DECLARE(const char *)apr_pencode_base32(apr_pool_t * p, const char *src,
779                              apr_ssize_t slen, int flags, apr_size_t * len)
780{
781    apr_size_t size;
782
783    switch (apr_encode_base32(NULL, src, slen, flags, &size)) {
784    case APR_SUCCESS:{
785            char *cmd = apr_palloc(p, size);
786            apr_encode_base32(cmd, src, slen, flags, len);
787            return cmd;
788        }
789    case APR_NOTFOUND:{
790            break;
791        }
792    }
793
794    return NULL;
795}
796
797APR_DECLARE(const char *)apr_pencode_base32_binary(apr_pool_t * p, const unsigned char *src,
798                              apr_ssize_t slen, int flags, apr_size_t * len)
799{
800    apr_size_t size;
801
802    switch (apr_encode_base32_binary(NULL, src, slen, flags, &size)) {
803    case APR_SUCCESS:{
804            char *cmd = apr_palloc(p, size);
805            apr_encode_base32_binary(cmd, src, slen, flags, len);
806            return cmd;
807        }
808    case APR_NOTFOUND:{
809            break;
810        }
811    }
812
813    return NULL;
814}
815
816APR_DECLARE(apr_status_t) apr_decode_base32(char *dest, const char *src,
817                              apr_ssize_t slen, int flags, apr_size_t * len)
818{
819    if (!src) {
820        return APR_NOTFOUND;
821    }
822
823    if (APR_ENCODE_STRING == slen) {
824        slen = strlen(src);
825    }
826
827    if (dest) {
828        register const unsigned char *bufin;
829        register unsigned char *bufout;
830        register apr_size_t nprbytes;
831        register apr_size_t count = slen;
832
833        const unsigned char *pr2;
834
835        apr_status_t status;
836
837        if ((flags & APR_ENCODE_BASE32HEX)) {
838            pr2 = pr2fivehex;
839        }
840        else {
841            pr2 = pr2five;
842        }
843
844        bufin = (const unsigned char *)src;
845        while (pr2[*(bufin++)] < 32 && count)
846            count--;
847        nprbytes = (bufin - (const unsigned char *)src) - 1;
848        while (pr2[*(bufin++)] > 32 && count)
849            count--;
850
851        status = flags & APR_ENCODE_RELAXED ? APR_SUCCESS :
852            count ? APR_BADCH : APR_SUCCESS;
853
854        bufout = (unsigned char *)dest;
855        bufin = (const unsigned char *)src;
856
857        while (nprbytes > 8) {
858            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[0]] << 3
859                                                      | pr2[bufin[1]] >> 2);
860            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[1]] << 6
861                                 | pr2[bufin[2]] << 1 | pr2[bufin[3]] >> 4);
862            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[3]] << 4
863                                                      | pr2[bufin[4]] >> 1);
864            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[4]] << 7
865                                 | pr2[bufin[5]] << 2 | pr2[bufin[6]] >> 3);
866            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[6]] << 5
867                                                          | pr2[bufin[7]]);
868            bufin += 8;
869            nprbytes -= 8;
870        }
871
872        if (nprbytes == 1) {
873            status = APR_BADCH;
874        }
875        if (nprbytes >= 2) {
876            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
877                                   pr2[bufin[0]] << 3 | pr2[bufin[1]] >> 2);
878        }
879        if (nprbytes == 3) {
880            status = APR_BADCH;
881        }
882        if (nprbytes >= 4) {
883            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
884                                     pr2[bufin[1]] << 6 | pr2[bufin[2]] << 1
885                                                      | pr2[bufin[3]] >> 4);
886        }
887        if (nprbytes >= 5) {
888            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[3]] << 4
889                                                      | pr2[bufin[4]] >> 1);
890        }
891        if (nprbytes == 6) {
892            status = APR_BADCH;
893        }
894        if (nprbytes >= 7) {
895            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[4]] << 7
896                                 | pr2[bufin[5]] << 2 | pr2[bufin[6]] >> 3);
897        }
898        if (nprbytes == 8) {
899            *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(pr2[bufin[6]] << 5
900                                                          | pr2[bufin[7]]);
901        }
902
903        if (len) {
904            *len = bufout - (unsigned char *)dest;
905        }
906
907        *(bufout++) = 0;
908
909        return status;
910    }
911
912    if (len) {
913        *len = (((int)slen + 7) / 8) * 5 + 1;
914    }
915
916    return APR_SUCCESS;
917}
918
919APR_DECLARE(apr_status_t) apr_decode_base32_binary(unsigned char *dest,
920             const char *src, apr_ssize_t slen, int flags, apr_size_t * len)
921{
922    if (!src) {
923        return APR_NOTFOUND;
924    }
925
926    if (APR_ENCODE_STRING == slen) {
927        slen = strlen(src);
928    }
929
930    if (dest) {
931        register const unsigned char *bufin;
932        register unsigned char *bufout;
933        register apr_size_t nprbytes;
934        register apr_size_t count = slen;
935
936        const unsigned char *pr2;
937
938        apr_status_t status;
939
940        if ((flags & APR_ENCODE_BASE32HEX)) {
941            pr2 = pr2fivehex;
942        }
943        else {
944            pr2 = pr2five;
945        }
946
947        bufin = (const unsigned char *)src;
948        while (pr2[*(bufin++)] < 32 && count)
949            count--;
950        nprbytes = (bufin - (const unsigned char *)src) - 1;
951        while (pr2[*(bufin++)] > 32 && count)
952            count--;
953
954        status = flags & APR_ENCODE_RELAXED ? APR_SUCCESS :
955            count ? APR_BADCH : APR_SUCCESS;
956
957        bufout = (unsigned char *)dest;
958        bufin = (const unsigned char *)src;
959
960        while (nprbytes > 8) {
961            *(bufout++) = (unsigned char)(pr2[bufin[0]] << 3
962                                          | pr2[bufin[1]] >> 2);
963            *(bufout++) = (unsigned char)(pr2[bufin[1]] << 6
964                                 | pr2[bufin[2]] << 1 | pr2[bufin[3]] >> 4);
965            *(bufout++) = (unsigned char)(pr2[bufin[3]] << 4
966                                          | pr2[bufin[4]] >> 1);
967            *(bufout++) = (unsigned char)(pr2[bufin[4]] << 7
968                                 | pr2[bufin[5]] << 2 | pr2[bufin[6]] >> 3);
969            *(bufout++) = (unsigned char)(pr2[bufin[6]] << 5
970                                          | pr2[bufin[7]]);
971            bufin += 8;
972            nprbytes -= 8;
973        }
974
975        if (nprbytes == 1) {
976            status = APR_BADCH;
977        }
978        if (nprbytes >= 2) {
979            *(bufout++) = (unsigned char)(
980                                   pr2[bufin[0]] << 3 | pr2[bufin[1]] >> 2);
981        }
982        if (nprbytes == 3) {
983            status = APR_BADCH;
984        }
985        if (nprbytes >= 4) {
986            *(bufout++) = (unsigned char)(
987                                     pr2[bufin[1]] << 6 | pr2[bufin[2]] << 1
988                                          | pr2[bufin[3]] >> 4);
989        }
990        if (nprbytes >= 5) {
991            *(bufout++) = (unsigned char)(pr2[bufin[3]] << 4
992                                          | pr2[bufin[4]] >> 1);
993        }
994        if (nprbytes == 6) {
995            status = APR_BADCH;
996        }
997        if (nprbytes >= 7) {
998            *(bufout++) = (unsigned char)(pr2[bufin[4]] << 7
999                                 | pr2[bufin[5]] << 2 | pr2[bufin[6]] >> 3);
1000        }
1001        if (nprbytes == 8) {
1002            *(bufout++) = (unsigned char)(pr2[bufin[6]] << 5
1003                                          | pr2[bufin[7]]);
1004        }
1005
1006        if (len) {
1007            *len = bufout - dest;
1008        }
1009
1010        return status;
1011    }
1012
1013    if (len) {
1014        *len = (((int)slen + 7) / 8) * 5;
1015    }
1016
1017    return APR_SUCCESS;
1018}
1019
1020APR_DECLARE(const char *)apr_pdecode_base32(apr_pool_t * p, const char *str,
1021                              apr_ssize_t slen, int flags, apr_size_t * len)
1022{
1023    apr_size_t size;
1024
1025    switch (apr_decode_base32(NULL, str, slen, flags, &size)) {
1026    case APR_SUCCESS:{
1027            void *cmd = apr_palloc(p, size);
1028            apr_decode_base32(cmd, str, slen, flags, len);
1029            return cmd;
1030        }
1031    case APR_BADCH:
1032    case APR_NOTFOUND:{
1033            break;
1034        }
1035    }
1036
1037    return NULL;
1038}
1039
1040APR_DECLARE(const unsigned char *)apr_pdecode_base32_binary(apr_pool_t * p,
1041             const char *str, apr_ssize_t slen, int flags, apr_size_t * len)
1042{
1043    apr_size_t size;
1044
1045    switch (apr_decode_base32_binary(NULL, str, slen, flags, &size)) {
1046    case APR_SUCCESS:{
1047            unsigned char *cmd = apr_palloc(p, size + 1);
1048            cmd[size] = 0;
1049            apr_decode_base32_binary(cmd, str, slen, flags, len);
1050            return cmd;
1051        }
1052    case APR_BADCH:
1053    case APR_NOTFOUND:{
1054            break;
1055        }
1056    }
1057
1058    return NULL;
1059}
1060
1061APR_DECLARE(apr_status_t) apr_encode_base16(char *dest,
1062             const char *src, apr_ssize_t slen, int flags, apr_size_t * len)
1063{
1064    const char *in = src;
1065    apr_size_t size;
1066
1067    if (!src) {
1068        return APR_NOTFOUND;
1069    }
1070
1071    if (dest) {
1072        register char *bufout = dest;
1073        const char *base;
1074
1075        if ((flags & APR_ENCODE_LOWER)) {
1076            base = base16lower;
1077        }
1078        else {
1079            base = base16;
1080        }
1081
1082        for (size = 0; (APR_ENCODE_STRING == slen) ? in[size] : size < slen; size++) {
1083            if ((flags & APR_ENCODE_COLON) && size) {
1084                *(bufout++) = ':';
1085            }
1086            *(bufout++) = base[(const unsigned char)(ENCODE_TO_ASCII(in[size])) >> 4];
1087            *(bufout++) = base[(const unsigned char)(ENCODE_TO_ASCII(in[size])) & 0xf];
1088        }
1089
1090        if (len) {
1091            *len = bufout - dest;
1092        }
1093
1094        *bufout = '\0';
1095
1096        return APR_SUCCESS;
1097    }
1098
1099    if (len) {
1100        if (APR_ENCODE_STRING == slen) {
1101            slen = strlen(src);
1102        }
1103        if ((flags & APR_ENCODE_COLON) && slen) {
1104            *len = slen * 3;
1105        }
1106        else {
1107            *len = slen * 2 + 1;
1108        }
1109    }
1110
1111    return APR_SUCCESS;
1112}
1113
1114APR_DECLARE(apr_status_t) apr_encode_base16_binary(char *dest,
1115    const unsigned char *src, apr_ssize_t slen, int flags, apr_size_t * len)
1116{
1117    const unsigned char *in = src;
1118    apr_size_t size;
1119
1120    if (!src) {
1121        return APR_NOTFOUND;
1122    }
1123
1124    if (dest) {
1125        register char *bufout = dest;
1126        const char *base;
1127
1128        if ((flags & APR_ENCODE_LOWER)) {
1129            base = base16lower;
1130        }
1131        else {
1132            base = base16;
1133        }
1134
1135        for (size = 0; size < slen; size++) {
1136            if ((flags & APR_ENCODE_COLON) && size) {
1137                *(bufout++) = ':';
1138            }
1139            *(bufout++) = base[in[size] >> 4];
1140            *(bufout++) = base[in[size] & 0xf];
1141        }
1142
1143        if (len) {
1144            *len = bufout - dest;
1145        }
1146
1147        *bufout = 0;
1148
1149        return APR_SUCCESS;
1150    }
1151
1152    if (len) {
1153        if ((flags & APR_ENCODE_COLON) && slen) {
1154            *len = slen * 3;
1155        }
1156        else {
1157            *len = slen * 2 + 1;
1158        }
1159    }
1160
1161    return APR_SUCCESS;
1162}
1163
1164APR_DECLARE(const char *)apr_pencode_base16(apr_pool_t * p,
1165             const char *src, apr_ssize_t slen, int flags, apr_size_t * len)
1166{
1167    apr_size_t size;
1168
1169    switch (apr_encode_base16(NULL, src, slen, flags, &size)) {
1170    case APR_SUCCESS:{
1171            char *cmd = apr_palloc(p, size);
1172            apr_encode_base16(cmd, src, slen, flags, len);
1173            return cmd;
1174        }
1175    case APR_NOTFOUND:{
1176            break;
1177        }
1178    }
1179
1180    return NULL;
1181}
1182
1183APR_DECLARE(const char *)apr_pencode_base16_binary(apr_pool_t * p,
1184                      const unsigned char *src, apr_ssize_t slen, int flags,
1185                                                   apr_size_t * len)
1186{
1187    apr_size_t size;
1188
1189    switch (apr_encode_base16_binary(NULL, src, slen, flags, &size)) {
1190    case APR_SUCCESS:{
1191            char *cmd = apr_palloc(p, size);
1192            apr_encode_base16_binary(cmd, src, slen, flags, len);
1193            return cmd;
1194        }
1195    case APR_NOTFOUND:{
1196            break;
1197        }
1198    }
1199
1200    return NULL;
1201}
1202
1203APR_DECLARE(apr_status_t) apr_decode_base16(char *dest,
1204             const char *src, apr_ssize_t slen, int flags, apr_size_t * len)
1205{
1206    register const unsigned char *bufin;
1207    register unsigned char *bufout;
1208    register apr_size_t nprbytes;
1209    register apr_size_t count;
1210
1211    apr_status_t status;
1212
1213    if (!src) {
1214        return APR_NOTFOUND;
1215    }
1216
1217    if (APR_ENCODE_STRING == slen) {
1218        slen = strlen(src);
1219    }
1220
1221    count = slen;
1222    bufin = (const unsigned char *)src;
1223    while (pr2two[*(bufin++)] != 16 && count)
1224        count--;
1225    nprbytes = (bufin - (const unsigned char *)src) - 1;
1226    while (pr2two[*(bufin++)] > 16 && count)
1227        count--;
1228
1229    status = flags & APR_ENCODE_RELAXED ? APR_SUCCESS :
1230        count ? APR_BADCH : APR_SUCCESS;
1231
1232    if (dest) {
1233
1234        bufout = (unsigned char *)dest;
1235        bufin = (const unsigned char *)src;
1236
1237        while (nprbytes >= 2) {
1238            if (pr2two[bufin[0]] > 16) {
1239                bufin += 1;
1240                nprbytes -= 1;
1241            }
1242            else {
1243                *(bufout++) = (unsigned char)ENCODE_TO_NATIVE(
1244                                  pr2two[bufin[0]] << 4 | pr2two[bufin[1]]);
1245                bufin += 2;
1246                nprbytes -= 2;
1247            }
1248        }
1249
1250        if (nprbytes == 1) {
1251            status = APR_BADCH;
1252        }
1253
1254        if (len) {
1255            *len = bufout - (unsigned char *)dest;
1256        }
1257
1258        *(bufout++) = 0;
1259
1260        return status;
1261    }
1262
1263    else {
1264
1265        count = 0;
1266        bufin = (const unsigned char *)src;
1267
1268        while (nprbytes >= 2) {
1269            if (pr2two[bufin[0]] > 16) {
1270                bufin += 1;
1271                nprbytes -= 1;
1272            }
1273            else {
1274                count++;
1275                bufin += 2;
1276                nprbytes -= 2;
1277            }
1278        }
1279
1280        if (nprbytes == 1) {
1281            status = APR_BADCH;
1282        }
1283
1284        if (len) {
1285            *len = count + 1;
1286        }
1287
1288        return status;
1289    }
1290
1291}
1292
1293APR_DECLARE(apr_status_t) apr_decode_base16_binary(unsigned char *dest,
1294             const char *src, apr_ssize_t slen, int flags, apr_size_t * len)
1295{
1296    register const unsigned char *bufin;
1297    register unsigned char *bufout;
1298    register apr_size_t nprbytes;
1299    register apr_size_t count;
1300
1301    apr_status_t status;
1302
1303    if (!src) {
1304        return APR_NOTFOUND;
1305    }
1306
1307    if (APR_ENCODE_STRING == slen) {
1308        slen = strlen(src);
1309    }
1310
1311    count = slen;
1312    bufin = (const unsigned char *)src;
1313    while (pr2two[*(bufin++)] != 16 && count)
1314        count--;
1315    nprbytes = (bufin - (const unsigned char *)src) - 1;
1316    while (pr2two[*(bufin++)] > 16 && count)
1317        count--;
1318
1319    status = flags & APR_ENCODE_RELAXED ? APR_SUCCESS :
1320        count ? APR_BADCH : APR_SUCCESS;
1321
1322    if (dest) {
1323
1324        bufout = (unsigned char *)dest;
1325        bufin = (const unsigned char *)src;
1326
1327        while (nprbytes >= 2) {
1328            if (pr2two[bufin[0]] > 16) {
1329                bufin += 1;
1330                nprbytes -= 1;
1331            }
1332            else {
1333                *(bufout++) = (unsigned char)(
1334                                  pr2two[bufin[0]] << 4 | pr2two[bufin[1]]);
1335                bufin += 2;
1336                nprbytes -= 2;
1337            }
1338        }
1339
1340        if (nprbytes == 1) {
1341            status = APR_BADCH;
1342        }
1343
1344        if (len) {
1345            *len = bufout - (unsigned char *)dest;
1346        }
1347
1348        return status;
1349    }
1350
1351    else {
1352
1353        count = 0;
1354        bufin = (const unsigned char *)src;
1355
1356        while (nprbytes >= 2) {
1357            if (pr2two[bufin[0]] > 16) {
1358                bufin += 1;
1359                nprbytes -= 1;
1360            }
1361            else {
1362                count++;
1363                bufin += 2;
1364                nprbytes -= 2;
1365            }
1366        }
1367
1368        if (nprbytes == 1) {
1369            status = APR_BADCH;
1370        }
1371
1372        if (len) {
1373            *len = count;
1374        }
1375
1376        return status;
1377    }
1378}
1379
1380APR_DECLARE(const char *)apr_pdecode_base16(apr_pool_t * p,
1381             const char *str, apr_ssize_t slen, int flags, apr_size_t * len)
1382{
1383    apr_size_t size;
1384
1385    switch (apr_decode_base16(NULL, str, slen, flags, &size)) {
1386    case APR_SUCCESS:{
1387            void *cmd = apr_palloc(p, size);
1388            apr_decode_base16(cmd, str, slen, flags, len);
1389            return cmd;
1390        }
1391    case APR_BADCH:
1392    case APR_NOTFOUND:{
1393            break;
1394        }
1395    }
1396
1397    return NULL;
1398}
1399
1400APR_DECLARE(const unsigned char *)apr_pdecode_base16_binary(apr_pool_t * p,
1401             const char *str, apr_ssize_t slen, int flags, apr_size_t * len)
1402{
1403    apr_size_t size;
1404
1405    switch (apr_decode_base16_binary(NULL, str, slen, flags, &size)) {
1406    case APR_SUCCESS:{
1407            unsigned char *cmd = apr_palloc(p, size + 1);
1408            cmd[size] = 0;
1409            apr_decode_base16_binary(cmd, str, slen, flags, len);
1410            return cmd;
1411        }
1412    case APR_BADCH:
1413    case APR_NOTFOUND:{
1414            break;
1415        }
1416    }
1417
1418    return NULL;
1419}
1420