1d4af9e69SDag-Erling Smørgrav /* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */
283d2307dSDag-Erling Smørgrav
383d2307dSDag-Erling Smørgrav /*
483d2307dSDag-Erling Smørgrav * Copyright (c) 1996 by Internet Software Consortium.
583d2307dSDag-Erling Smørgrav *
683d2307dSDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any
783d2307dSDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above
883d2307dSDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies.
983d2307dSDag-Erling Smørgrav *
1083d2307dSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1183d2307dSDag-Erling Smørgrav * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1283d2307dSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1383d2307dSDag-Erling Smørgrav * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1483d2307dSDag-Erling Smørgrav * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1583d2307dSDag-Erling Smørgrav * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1683d2307dSDag-Erling Smørgrav * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1783d2307dSDag-Erling Smørgrav * SOFTWARE.
1883d2307dSDag-Erling Smørgrav */
1983d2307dSDag-Erling Smørgrav
2083d2307dSDag-Erling Smørgrav /*
2183d2307dSDag-Erling Smørgrav * Portions Copyright (c) 1995 by International Business Machines, Inc.
2283d2307dSDag-Erling Smørgrav *
2383d2307dSDag-Erling Smørgrav * International Business Machines, Inc. (hereinafter called IBM) grants
2483d2307dSDag-Erling Smørgrav * permission under its copyrights to use, copy, modify, and distribute this
2583d2307dSDag-Erling Smørgrav * Software with or without fee, provided that the above copyright notice and
2683d2307dSDag-Erling Smørgrav * all paragraphs of this notice appear in all copies, and that the name of IBM
2783d2307dSDag-Erling Smørgrav * not be used in connection with the marketing of any product incorporating
2883d2307dSDag-Erling Smørgrav * the Software or modifications thereof, without specific, written prior
2983d2307dSDag-Erling Smørgrav * permission.
3083d2307dSDag-Erling Smørgrav *
3183d2307dSDag-Erling Smørgrav * To the extent it has a right to do so, IBM grants an immunity from suit
3283d2307dSDag-Erling Smørgrav * under its patents, if any, for the use, sale or manufacture of products to
3383d2307dSDag-Erling Smørgrav * the extent that such products are used for performing Domain Name System
3483d2307dSDag-Erling Smørgrav * dynamic updates in TCP/IP networks by means of the Software. No immunity is
3583d2307dSDag-Erling Smørgrav * granted for any product per se or for any other function of any product.
3683d2307dSDag-Erling Smørgrav *
3783d2307dSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
3883d2307dSDag-Erling Smørgrav * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
3983d2307dSDag-Erling Smørgrav * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
4083d2307dSDag-Erling Smørgrav * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
4183d2307dSDag-Erling Smørgrav * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
4283d2307dSDag-Erling Smørgrav * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
4383d2307dSDag-Erling Smørgrav */
4483d2307dSDag-Erling Smørgrav
45021d409fSDag-Erling Smørgrav /* OPENBSD ORIGINAL: lib/libc/net/base64.c */
46021d409fSDag-Erling Smørgrav
474b17dab0SDag-Erling Smørgrav #include "includes.h"
4883d2307dSDag-Erling Smørgrav
49d0c8c0bcSDag-Erling Smørgrav #if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON))
5083d2307dSDag-Erling Smørgrav
5183d2307dSDag-Erling Smørgrav #include <sys/types.h>
5283d2307dSDag-Erling Smørgrav #include <sys/socket.h>
5383d2307dSDag-Erling Smørgrav #include <netinet/in.h>
5483d2307dSDag-Erling Smørgrav #include <arpa/inet.h>
5583d2307dSDag-Erling Smørgrav
5683d2307dSDag-Erling Smørgrav #include <ctype.h>
5783d2307dSDag-Erling Smørgrav #include <stdio.h>
5883d2307dSDag-Erling Smørgrav
5983d2307dSDag-Erling Smørgrav #include <stdlib.h>
6083d2307dSDag-Erling Smørgrav #include <string.h>
6183d2307dSDag-Erling Smørgrav
6283d2307dSDag-Erling Smørgrav #include "base64.h"
6383d2307dSDag-Erling Smørgrav
6483d2307dSDag-Erling Smørgrav static const char Base64[] =
6583d2307dSDag-Erling Smørgrav "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6683d2307dSDag-Erling Smørgrav static const char Pad64 = '=';
6783d2307dSDag-Erling Smørgrav
6883d2307dSDag-Erling Smørgrav /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
6983d2307dSDag-Erling Smørgrav The following encoding technique is taken from RFC 1521 by Borenstein
7083d2307dSDag-Erling Smørgrav and Freed. It is reproduced here in a slightly edited form for
7183d2307dSDag-Erling Smørgrav convenience.
7283d2307dSDag-Erling Smørgrav
7383d2307dSDag-Erling Smørgrav A 65-character subset of US-ASCII is used, enabling 6 bits to be
7483d2307dSDag-Erling Smørgrav represented per printable character. (The extra 65th character, "=",
7583d2307dSDag-Erling Smørgrav is used to signify a special processing function.)
7683d2307dSDag-Erling Smørgrav
7783d2307dSDag-Erling Smørgrav The encoding process represents 24-bit groups of input bits as output
7883d2307dSDag-Erling Smørgrav strings of 4 encoded characters. Proceeding from left to right, a
7983d2307dSDag-Erling Smørgrav 24-bit input group is formed by concatenating 3 8-bit input groups.
8083d2307dSDag-Erling Smørgrav These 24 bits are then treated as 4 concatenated 6-bit groups, each
8183d2307dSDag-Erling Smørgrav of which is translated into a single digit in the base64 alphabet.
8283d2307dSDag-Erling Smørgrav
8383d2307dSDag-Erling Smørgrav Each 6-bit group is used as an index into an array of 64 printable
8483d2307dSDag-Erling Smørgrav characters. The character referenced by the index is placed in the
8583d2307dSDag-Erling Smørgrav output string.
8683d2307dSDag-Erling Smørgrav
8783d2307dSDag-Erling Smørgrav Table 1: The Base64 Alphabet
8883d2307dSDag-Erling Smørgrav
8983d2307dSDag-Erling Smørgrav Value Encoding Value Encoding Value Encoding Value Encoding
9083d2307dSDag-Erling Smørgrav 0 A 17 R 34 i 51 z
9183d2307dSDag-Erling Smørgrav 1 B 18 S 35 j 52 0
9283d2307dSDag-Erling Smørgrav 2 C 19 T 36 k 53 1
9383d2307dSDag-Erling Smørgrav 3 D 20 U 37 l 54 2
9483d2307dSDag-Erling Smørgrav 4 E 21 V 38 m 55 3
9583d2307dSDag-Erling Smørgrav 5 F 22 W 39 n 56 4
9683d2307dSDag-Erling Smørgrav 6 G 23 X 40 o 57 5
9783d2307dSDag-Erling Smørgrav 7 H 24 Y 41 p 58 6
9883d2307dSDag-Erling Smørgrav 8 I 25 Z 42 q 59 7
9983d2307dSDag-Erling Smørgrav 9 J 26 a 43 r 60 8
10083d2307dSDag-Erling Smørgrav 10 K 27 b 44 s 61 9
10183d2307dSDag-Erling Smørgrav 11 L 28 c 45 t 62 +
10283d2307dSDag-Erling Smørgrav 12 M 29 d 46 u 63 /
10383d2307dSDag-Erling Smørgrav 13 N 30 e 47 v
10483d2307dSDag-Erling Smørgrav 14 O 31 f 48 w (pad) =
10583d2307dSDag-Erling Smørgrav 15 P 32 g 49 x
10683d2307dSDag-Erling Smørgrav 16 Q 33 h 50 y
10783d2307dSDag-Erling Smørgrav
10883d2307dSDag-Erling Smørgrav Special processing is performed if fewer than 24 bits are available
10983d2307dSDag-Erling Smørgrav at the end of the data being encoded. A full encoding quantum is
11083d2307dSDag-Erling Smørgrav always completed at the end of a quantity. When fewer than 24 input
11183d2307dSDag-Erling Smørgrav bits are available in an input group, zero bits are added (on the
11283d2307dSDag-Erling Smørgrav right) to form an integral number of 6-bit groups. Padding at the
11383d2307dSDag-Erling Smørgrav end of the data is performed using the '=' character.
11483d2307dSDag-Erling Smørgrav
11583d2307dSDag-Erling Smørgrav Since all base64 input is an integral number of octets, only the
11683d2307dSDag-Erling Smørgrav -------------------------------------------------
11783d2307dSDag-Erling Smørgrav following cases can arise:
11883d2307dSDag-Erling Smørgrav
11983d2307dSDag-Erling Smørgrav (1) the final quantum of encoding input is an integral
12083d2307dSDag-Erling Smørgrav multiple of 24 bits; here, the final unit of encoded
12183d2307dSDag-Erling Smørgrav output will be an integral multiple of 4 characters
12283d2307dSDag-Erling Smørgrav with no "=" padding,
12383d2307dSDag-Erling Smørgrav (2) the final quantum of encoding input is exactly 8 bits;
12483d2307dSDag-Erling Smørgrav here, the final unit of encoded output will be two
12583d2307dSDag-Erling Smørgrav characters followed by two "=" padding characters, or
12683d2307dSDag-Erling Smørgrav (3) the final quantum of encoding input is exactly 16 bits;
12783d2307dSDag-Erling Smørgrav here, the final unit of encoded output will be three
12883d2307dSDag-Erling Smørgrav characters followed by one "=" padding character.
12983d2307dSDag-Erling Smørgrav */
13083d2307dSDag-Erling Smørgrav
131d0c8c0bcSDag-Erling Smørgrav #if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)
13283d2307dSDag-Erling Smørgrav int
b64_ntop(u_char const * src,size_t srclength,char * target,size_t targsize)13383d2307dSDag-Erling Smørgrav b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
13483d2307dSDag-Erling Smørgrav {
13583d2307dSDag-Erling Smørgrav size_t datalength = 0;
13683d2307dSDag-Erling Smørgrav u_char input[3];
13783d2307dSDag-Erling Smørgrav u_char output[4];
138021d409fSDag-Erling Smørgrav u_int i;
13983d2307dSDag-Erling Smørgrav
14083d2307dSDag-Erling Smørgrav while (2 < srclength) {
14183d2307dSDag-Erling Smørgrav input[0] = *src++;
14283d2307dSDag-Erling Smørgrav input[1] = *src++;
14383d2307dSDag-Erling Smørgrav input[2] = *src++;
14483d2307dSDag-Erling Smørgrav srclength -= 3;
14583d2307dSDag-Erling Smørgrav
14683d2307dSDag-Erling Smørgrav output[0] = input[0] >> 2;
14783d2307dSDag-Erling Smørgrav output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
14883d2307dSDag-Erling Smørgrav output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
14983d2307dSDag-Erling Smørgrav output[3] = input[2] & 0x3f;
15083d2307dSDag-Erling Smørgrav
15183d2307dSDag-Erling Smørgrav if (datalength + 4 > targsize)
15283d2307dSDag-Erling Smørgrav return (-1);
15383d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[0]];
15483d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[1]];
15583d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[2]];
15683d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[3]];
15783d2307dSDag-Erling Smørgrav }
15883d2307dSDag-Erling Smørgrav
15983d2307dSDag-Erling Smørgrav /* Now we worry about padding. */
16083d2307dSDag-Erling Smørgrav if (0 != srclength) {
16183d2307dSDag-Erling Smørgrav /* Get what's left. */
16283d2307dSDag-Erling Smørgrav input[0] = input[1] = input[2] = '\0';
16383d2307dSDag-Erling Smørgrav for (i = 0; i < srclength; i++)
16483d2307dSDag-Erling Smørgrav input[i] = *src++;
16583d2307dSDag-Erling Smørgrav
16683d2307dSDag-Erling Smørgrav output[0] = input[0] >> 2;
16783d2307dSDag-Erling Smørgrav output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
16883d2307dSDag-Erling Smørgrav output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
16983d2307dSDag-Erling Smørgrav
17083d2307dSDag-Erling Smørgrav if (datalength + 4 > targsize)
17183d2307dSDag-Erling Smørgrav return (-1);
17283d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[0]];
17383d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[1]];
17483d2307dSDag-Erling Smørgrav if (srclength == 1)
17583d2307dSDag-Erling Smørgrav target[datalength++] = Pad64;
17683d2307dSDag-Erling Smørgrav else
17783d2307dSDag-Erling Smørgrav target[datalength++] = Base64[output[2]];
17883d2307dSDag-Erling Smørgrav target[datalength++] = Pad64;
17983d2307dSDag-Erling Smørgrav }
18083d2307dSDag-Erling Smørgrav if (datalength >= targsize)
18183d2307dSDag-Erling Smørgrav return (-1);
18283d2307dSDag-Erling Smørgrav target[datalength] = '\0'; /* Returned value doesn't count \0. */
18383d2307dSDag-Erling Smørgrav return (datalength);
18483d2307dSDag-Erling Smørgrav }
185d0c8c0bcSDag-Erling Smørgrav #endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */
186d0c8c0bcSDag-Erling Smørgrav
187d0c8c0bcSDag-Erling Smørgrav #if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)
18883d2307dSDag-Erling Smørgrav
18983d2307dSDag-Erling Smørgrav /* skips all whitespace anywhere.
19083d2307dSDag-Erling Smørgrav converts characters, four at a time, starting at (or after)
19183d2307dSDag-Erling Smørgrav src from base - 64 numbers into three 8 bit bytes in the target area.
19283d2307dSDag-Erling Smørgrav it returns the number of data bytes stored at the target, or -1 on error.
19383d2307dSDag-Erling Smørgrav */
19483d2307dSDag-Erling Smørgrav
19583d2307dSDag-Erling Smørgrav int
b64_pton(char const * src,u_char * target,size_t targsize)19683d2307dSDag-Erling Smørgrav b64_pton(char const *src, u_char *target, size_t targsize)
19783d2307dSDag-Erling Smørgrav {
198021d409fSDag-Erling Smørgrav u_int tarindex, state;
199021d409fSDag-Erling Smørgrav int ch;
20083d2307dSDag-Erling Smørgrav char *pos;
20183d2307dSDag-Erling Smørgrav
20283d2307dSDag-Erling Smørgrav state = 0;
20383d2307dSDag-Erling Smørgrav tarindex = 0;
20483d2307dSDag-Erling Smørgrav
20583d2307dSDag-Erling Smørgrav while ((ch = *src++) != '\0') {
20683d2307dSDag-Erling Smørgrav if (isspace(ch)) /* Skip whitespace anywhere. */
20783d2307dSDag-Erling Smørgrav continue;
20883d2307dSDag-Erling Smørgrav
20983d2307dSDag-Erling Smørgrav if (ch == Pad64)
21083d2307dSDag-Erling Smørgrav break;
21183d2307dSDag-Erling Smørgrav
21283d2307dSDag-Erling Smørgrav pos = strchr(Base64, ch);
21383d2307dSDag-Erling Smørgrav if (pos == 0) /* A non-base64 character. */
21483d2307dSDag-Erling Smørgrav return (-1);
21583d2307dSDag-Erling Smørgrav
21683d2307dSDag-Erling Smørgrav switch (state) {
21783d2307dSDag-Erling Smørgrav case 0:
21883d2307dSDag-Erling Smørgrav if (target) {
21983d2307dSDag-Erling Smørgrav if (tarindex >= targsize)
22083d2307dSDag-Erling Smørgrav return (-1);
22183d2307dSDag-Erling Smørgrav target[tarindex] = (pos - Base64) << 2;
22283d2307dSDag-Erling Smørgrav }
22383d2307dSDag-Erling Smørgrav state = 1;
22483d2307dSDag-Erling Smørgrav break;
22583d2307dSDag-Erling Smørgrav case 1:
22683d2307dSDag-Erling Smørgrav if (target) {
22783d2307dSDag-Erling Smørgrav if (tarindex + 1 >= targsize)
22883d2307dSDag-Erling Smørgrav return (-1);
22983d2307dSDag-Erling Smørgrav target[tarindex] |= (pos - Base64) >> 4;
23083d2307dSDag-Erling Smørgrav target[tarindex+1] = ((pos - Base64) & 0x0f)
23183d2307dSDag-Erling Smørgrav << 4 ;
23283d2307dSDag-Erling Smørgrav }
23383d2307dSDag-Erling Smørgrav tarindex++;
23483d2307dSDag-Erling Smørgrav state = 2;
23583d2307dSDag-Erling Smørgrav break;
23683d2307dSDag-Erling Smørgrav case 2:
23783d2307dSDag-Erling Smørgrav if (target) {
23883d2307dSDag-Erling Smørgrav if (tarindex + 1 >= targsize)
23983d2307dSDag-Erling Smørgrav return (-1);
24083d2307dSDag-Erling Smørgrav target[tarindex] |= (pos - Base64) >> 2;
24183d2307dSDag-Erling Smørgrav target[tarindex+1] = ((pos - Base64) & 0x03)
24283d2307dSDag-Erling Smørgrav << 6;
24383d2307dSDag-Erling Smørgrav }
24483d2307dSDag-Erling Smørgrav tarindex++;
24583d2307dSDag-Erling Smørgrav state = 3;
24683d2307dSDag-Erling Smørgrav break;
24783d2307dSDag-Erling Smørgrav case 3:
24883d2307dSDag-Erling Smørgrav if (target) {
24983d2307dSDag-Erling Smørgrav if (tarindex >= targsize)
25083d2307dSDag-Erling Smørgrav return (-1);
25183d2307dSDag-Erling Smørgrav target[tarindex] |= (pos - Base64);
25283d2307dSDag-Erling Smørgrav }
25383d2307dSDag-Erling Smørgrav tarindex++;
25483d2307dSDag-Erling Smørgrav state = 0;
25583d2307dSDag-Erling Smørgrav break;
25683d2307dSDag-Erling Smørgrav }
25783d2307dSDag-Erling Smørgrav }
25883d2307dSDag-Erling Smørgrav
25983d2307dSDag-Erling Smørgrav /*
26083d2307dSDag-Erling Smørgrav * We are done decoding Base-64 chars. Let's see if we ended
26183d2307dSDag-Erling Smørgrav * on a byte boundary, and/or with erroneous trailing characters.
26283d2307dSDag-Erling Smørgrav */
26383d2307dSDag-Erling Smørgrav
26483d2307dSDag-Erling Smørgrav if (ch == Pad64) { /* We got a pad char. */
26583d2307dSDag-Erling Smørgrav ch = *src++; /* Skip it, get next. */
26683d2307dSDag-Erling Smørgrav switch (state) {
26783d2307dSDag-Erling Smørgrav case 0: /* Invalid = in first position */
26883d2307dSDag-Erling Smørgrav case 1: /* Invalid = in second position */
26983d2307dSDag-Erling Smørgrav return (-1);
27083d2307dSDag-Erling Smørgrav
27183d2307dSDag-Erling Smørgrav case 2: /* Valid, means one byte of info */
27283d2307dSDag-Erling Smørgrav /* Skip any number of spaces. */
27383d2307dSDag-Erling Smørgrav for (; ch != '\0'; ch = *src++)
27483d2307dSDag-Erling Smørgrav if (!isspace(ch))
27583d2307dSDag-Erling Smørgrav break;
27683d2307dSDag-Erling Smørgrav /* Make sure there is another trailing = sign. */
27783d2307dSDag-Erling Smørgrav if (ch != Pad64)
27883d2307dSDag-Erling Smørgrav return (-1);
27983d2307dSDag-Erling Smørgrav ch = *src++; /* Skip the = */
28083d2307dSDag-Erling Smørgrav /* Fall through to "single trailing =" case. */
28183d2307dSDag-Erling Smørgrav /* FALLTHROUGH */
28283d2307dSDag-Erling Smørgrav
28383d2307dSDag-Erling Smørgrav case 3: /* Valid, means two bytes of info */
28483d2307dSDag-Erling Smørgrav /*
28583d2307dSDag-Erling Smørgrav * We know this char is an =. Is there anything but
28683d2307dSDag-Erling Smørgrav * whitespace after it?
28783d2307dSDag-Erling Smørgrav */
28883d2307dSDag-Erling Smørgrav for (; ch != '\0'; ch = *src++)
28983d2307dSDag-Erling Smørgrav if (!isspace(ch))
29083d2307dSDag-Erling Smørgrav return (-1);
29183d2307dSDag-Erling Smørgrav
29283d2307dSDag-Erling Smørgrav /*
29383d2307dSDag-Erling Smørgrav * Now make sure for cases 2 and 3 that the "extra"
29483d2307dSDag-Erling Smørgrav * bits that slopped past the last full byte were
29583d2307dSDag-Erling Smørgrav * zeros. If we don't check them, they become a
29683d2307dSDag-Erling Smørgrav * subliminal channel.
29783d2307dSDag-Erling Smørgrav */
29883d2307dSDag-Erling Smørgrav if (target && target[tarindex] != 0)
29983d2307dSDag-Erling Smørgrav return (-1);
30083d2307dSDag-Erling Smørgrav }
30183d2307dSDag-Erling Smørgrav } else {
30283d2307dSDag-Erling Smørgrav /*
30383d2307dSDag-Erling Smørgrav * We ended by seeing the end of the string. Make sure we
30483d2307dSDag-Erling Smørgrav * have no partial bytes lying around.
30583d2307dSDag-Erling Smørgrav */
30683d2307dSDag-Erling Smørgrav if (state != 0)
30783d2307dSDag-Erling Smørgrav return (-1);
30883d2307dSDag-Erling Smørgrav }
30983d2307dSDag-Erling Smørgrav
31083d2307dSDag-Erling Smørgrav return (tarindex);
31183d2307dSDag-Erling Smørgrav }
31283d2307dSDag-Erling Smørgrav
313d0c8c0bcSDag-Erling Smørgrav #endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */
314d0c8c0bcSDag-Erling Smørgrav #endif
315