Polish translation was updated.
[elinks.git] / src / util / base64.c
blobfc777174e7f47b2c1236ec116afc73c9b485b187
1 /* Base64 encode/decode implementation. */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <string.h>
9 #include "elinks.h"
11 #include "util/base64.h"
12 #include "util/error.h"
13 #include "util/memory.h"
15 static unsigned char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17 unsigned char *
18 base64_encode(register unsigned char *in)
20 assert(in && *in);
21 if_assert_failed return NULL;
23 return base64_encode_bin(in, strlen(in), NULL);
26 unsigned char *
27 base64_encode_bin(register unsigned char *in, int inlen, int *outlen)
29 unsigned char *out;
30 unsigned char *outstr;
32 assert(in && *in);
33 if_assert_failed return NULL;
35 out = outstr = mem_alloc((inlen / 3) * 4 + 4 + 1);
36 if (!out) return NULL;
38 while (inlen >= 3) {
39 *out++ = base64_chars[ *in >> 2 ];
40 *out++ = base64_chars[ (*in << 4 | *(in + 1) >> 4) & 63 ];
41 *out++ = base64_chars[ (*(in + 1) << 2 | *(in + 2) >> 6) & 63 ];
42 *out++ = base64_chars[ *(in + 2) & 63 ];
43 inlen -= 3; in += 3;
45 if (inlen == 1) {
46 *out++ = base64_chars[ *in >> 2 ];
47 *out++ = base64_chars[ *in << 4 & 63 ];
48 *out++ = '=';
49 *out++ = '=';
51 if (inlen == 2) {
52 *out++ = base64_chars[ *in >> 2 ];
53 *out++ = base64_chars[ (*in << 4 | *(in + 1) >> 4) & 63 ];
54 *out++ = base64_chars[ (*(in + 1) << 2) & 63 ];
55 *out++ = '=';
57 *out = 0;
59 if (outlen)
60 *outlen = out-outstr;
62 return outstr;
65 /* Base64 decoding is used only with the CONFIG_FORMHIST or CONFIG_GSSAPI
66 feature, so i'll #ifdef it */
67 #if defined(CONFIG_FORMHIST) || defined(CONFIG_GSSAPI)
69 unsigned char *
70 base64_decode(register unsigned char *in)
72 assert(in && *in);
73 if_assert_failed return NULL;
75 return base64_decode_bin(in, strlen(in), NULL);
78 /* base64_decode: @in string to decode
79 * returns the string decoded (must be freed by the caller) */
80 unsigned char *
81 base64_decode_bin(register unsigned char *in, int inlen, int *outlen)
83 static unsigned char is_base64_char[256]; /* static to force initialization at zero */
84 static unsigned char decode[256];
85 unsigned char *out;
86 unsigned char *outstr;
87 int count = 0;
88 unsigned int bits = 0;
89 static int once = 0;
91 assert(in && *in);
92 if_assert_failed return NULL;
94 outstr = out = mem_alloc(inlen / 4 * 3 + 1);
95 if (!outstr) return NULL;
97 if (!once) {
98 int i = sizeof(base64_chars) - 1;
100 while (i >= 0) {
101 is_base64_char[base64_chars[i]] = 1;
102 decode[base64_chars[i]] = i;
103 i--;
105 once = 1;
108 while (*in) {
109 if (*in == '=') break;
110 if (!is_base64_char[*in])
111 goto decode_error;
113 bits += decode[*in];
114 count++;
115 if (count == 4) {
116 *out++ = bits >> 16;
117 *out++ = (bits >> 8) & 0xff;
118 *out++ = bits & 0xff;
119 bits = 0;
120 count = 0;
121 } else {
122 bits <<= 6;
125 ++in;
128 if (!*in) {
129 if (count) goto decode_error;
130 } else { /* '=' */
131 switch (count) {
132 case 1:
133 goto decode_error;
134 break;
135 case 2:
136 *out++ = bits >> 10;
137 break;
138 case 3:
139 *out++ = bits >> 16;
140 *out++ = (bits >> 8) & 0xff;
141 break;
145 *out = 0;
147 if (outlen)
148 *outlen = out-outstr;
150 return outstr;
152 decode_error:
153 mem_free(outstr);
154 return NULL;
157 #endif /* CONFIG_FORMHIST */