Bug 880: Prevent SIGSEGV in init_python when -no-home is used.
[elinks.git] / src / util / base64.c
blob8a3918ea29b12fff54ca279c2ba3475e3b79451c
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 unsigned char *out;
21 unsigned char *outstr;
22 int inlen;
24 assert(in && *in);
25 if_assert_failed return NULL;
27 inlen = strlen(in);
28 out = outstr = mem_alloc((inlen / 3) * 4 + 4 + 1);
29 if (!out) return NULL;
31 while (inlen >= 3) {
32 *out++ = base64_chars[ *in >> 2 ];
33 *out++ = base64_chars[ (*in << 4 | *(in + 1) >> 4) & 63 ];
34 *out++ = base64_chars[ (*(in + 1) << 2 | *(in + 2) >> 6) & 63 ];
35 *out++ = base64_chars[ *(in + 2) & 63 ];
36 inlen -= 3; in += 3;
38 if (inlen == 1) {
39 *out++ = base64_chars[ *in >> 2 ];
40 *out++ = base64_chars[ *in << 4 & 63 ];
41 *out++ = '=';
42 *out++ = '=';
44 if (inlen == 2) {
45 *out++ = base64_chars[ *in >> 2 ];
46 *out++ = base64_chars[ (*in << 4 | *(in + 1) >> 4) & 63 ];
47 *out++ = base64_chars[ (*(in + 1) << 2) & 63 ];
48 *out++ = '=';
50 *out = 0;
52 return outstr;
55 /* Base64 decoding is used only with the CONFIG_FORMHIST feature, so i'll #ifdef it */
56 #ifdef CONFIG_FORMHIST
58 /* base64_decode: @in string to decode
59 * returns the string decoded (must be freed by the caller) */
60 unsigned char *
61 base64_decode(register unsigned char *in)
63 static unsigned char is_base64_char[256]; /* static to force initialization at zero */
64 static unsigned char decode[256];
65 unsigned char *out;
66 unsigned char *outstr;
67 int count = 0;
68 unsigned int bits = 0;
69 static int once = 0;
71 assert(in && *in);
72 if_assert_failed return NULL;
74 outstr = out = mem_alloc(strlen(in) / 4 * 3 + 1);
75 if (!outstr) return NULL;
77 if (!once) {
78 int i = sizeof(base64_chars) - 1;
80 while (i >= 0) {
81 is_base64_char[base64_chars[i]] = 1;
82 decode[base64_chars[i]] = i;
83 i--;
85 once = 1;
88 while (*in) {
89 if (*in == '=') break;
90 if (!is_base64_char[*in])
91 goto decode_error;
93 bits += decode[*in];
94 count++;
95 if (count == 4) {
96 *out++ = bits >> 16;
97 *out++ = (bits >> 8) & 0xff;
98 *out++ = bits & 0xff;
99 bits = 0;
100 count = 0;
101 } else {
102 bits <<= 6;
105 ++in;
108 if (!*in) {
109 if (count) goto decode_error;
110 } else { /* '=' */
111 switch (count) {
112 case 1:
113 goto decode_error;
114 break;
115 case 2:
116 *out++ = bits >> 10;
117 break;
118 case 3:
119 *out++ = bits >> 16;
120 *out++ = (bits >> 8) & 0xff;
121 break;
125 *out = 0;
126 return outstr;
128 decode_error:
129 mem_free(outstr);
130 return NULL;
133 #endif /* CONFIG_FORMHIST */