1 |
#include <util/base64.h> |
2 |
|
3 |
namespace base64 |
4 |
{ |
5 |
const int CHARS_PER_LINE = 72; |
6 |
|
7 |
void base64_init_encodestate (base64_encodestate * state_in) |
8 |
{ |
9 |
state_in->step = step_A; |
10 |
state_in->result = 0; |
11 |
state_in->stepcount = 0; |
12 |
} |
13 |
|
14 |
char base64_encode_value (char value_in) |
15 |
{ |
16 |
static const char *encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
17 |
if (value_in > 63) |
18 |
return '='; |
19 |
return encoding[(int) value_in]; |
20 |
} |
21 |
|
22 |
int base64_encode_block (const char *plaintext_in, int length_in, char *code_out, base64_encodestate * state_in) |
23 |
{ |
24 |
const char *plainchar = plaintext_in; |
25 |
const char *const plaintextend = plaintext_in + length_in; |
26 |
char *codechar = code_out; |
27 |
char result; |
28 |
char fragment; |
29 |
|
30 |
result = state_in->result; |
31 |
|
32 |
switch (state_in->step) |
33 |
{ |
34 |
while (1) |
35 |
{ |
36 |
case step_A: |
37 |
if (plainchar == plaintextend) |
38 |
{ |
39 |
state_in->result = result; |
40 |
state_in->step = step_A; |
41 |
return codechar - code_out; |
42 |
} |
43 |
fragment = *plainchar++; |
44 |
result = (fragment & 0x0fc) >> 2; |
45 |
*codechar++ = base64_encode_value (result); |
46 |
result = (fragment & 0x003) << 4; |
47 |
case step_B: |
48 |
if (plainchar == plaintextend) |
49 |
{ |
50 |
state_in->result = result; |
51 |
state_in->step = step_B; |
52 |
return codechar - code_out; |
53 |
} |
54 |
fragment = *plainchar++; |
55 |
result |= (fragment & 0x0f0) >> 4; |
56 |
*codechar++ = base64_encode_value (result); |
57 |
result = (fragment & 0x00f) << 2; |
58 |
case step_C: |
59 |
if (plainchar == plaintextend) |
60 |
{ |
61 |
state_in->result = result; |
62 |
state_in->step = step_C; |
63 |
return codechar - code_out; |
64 |
} |
65 |
fragment = *plainchar++; |
66 |
result |= (fragment & 0x0c0) >> 6; |
67 |
*codechar++ = base64_encode_value (result); |
68 |
result = (fragment & 0x03f) >> 0; |
69 |
*codechar++ = base64_encode_value (result); |
70 |
|
71 |
++(state_in->stepcount); |
72 |
if (state_in->stepcount == CHARS_PER_LINE / 4) |
73 |
{ |
74 |
*codechar++ = '\n'; |
75 |
state_in->stepcount = 0; |
76 |
} |
77 |
} |
78 |
} |
79 |
/* control should not reach here */ |
80 |
return codechar - code_out; |
81 |
} |
82 |
|
83 |
int base64_encode_blockend (char *code_out, base64_encodestate * state_in) |
84 |
{ |
85 |
char *codechar = code_out; |
86 |
|
87 |
switch (state_in->step) |
88 |
{ |
89 |
case step_B: |
90 |
*codechar++ = base64_encode_value (state_in->result); |
91 |
*codechar++ = '='; |
92 |
*codechar++ = '='; |
93 |
break; |
94 |
case step_C: |
95 |
*codechar++ = base64_encode_value (state_in->result); |
96 |
*codechar++ = '='; |
97 |
break; |
98 |
case step_A: |
99 |
break; |
100 |
} |
101 |
*codechar++ = '\n'; |
102 |
|
103 |
return codechar - code_out; |
104 |
} |
105 |
|
106 |
////////////////////// |
107 |
int base64_decode_value (char value_in) |
108 |
{ |
109 |
static const char decoding[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; |
110 |
static const char decoding_size = sizeof (decoding); |
111 |
value_in -= 43; |
112 |
if (value_in < 0 || value_in > decoding_size) |
113 |
return -1; |
114 |
return decoding[(int) value_in]; |
115 |
} |
116 |
|
117 |
void base64_init_decodestate (base64_decodestate * state_in) |
118 |
{ |
119 |
state_in->step = step_a; |
120 |
state_in->plainchar = 0; |
121 |
} |
122 |
|
123 |
int base64_decode_block (const char *code_in, const int length_in, char *plaintext_out, base64_decodestate * state_in) |
124 |
{ |
125 |
const char *codechar = code_in; |
126 |
char *plainchar = plaintext_out; |
127 |
char fragment; |
128 |
|
129 |
*plainchar = state_in->plainchar; |
130 |
|
131 |
switch (state_in->step) |
132 |
{ |
133 |
while (1) |
134 |
{ |
135 |
case step_a: |
136 |
do |
137 |
{ |
138 |
if (codechar == code_in + length_in) |
139 |
{ |
140 |
state_in->step = step_a; |
141 |
state_in->plainchar = *plainchar; |
142 |
return plainchar - plaintext_out; |
143 |
} |
144 |
fragment = (char) base64_decode_value (*codechar++); |
145 |
} |
146 |
while (fragment < 0); |
147 |
*plainchar = (fragment & 0x03f) << 2; |
148 |
case step_b: |
149 |
do |
150 |
{ |
151 |
if (codechar == code_in + length_in) |
152 |
{ |
153 |
state_in->step = step_b; |
154 |
state_in->plainchar = *plainchar; |
155 |
return plainchar - plaintext_out; |
156 |
} |
157 |
fragment = (char) base64_decode_value (*codechar++); |
158 |
} |
159 |
while (fragment < 0); |
160 |
*plainchar++ |= (fragment & 0x030) >> 4; |
161 |
*plainchar = (fragment & 0x00f) << 4; |
162 |
case step_c: |
163 |
do |
164 |
{ |
165 |
if (codechar == code_in + length_in) |
166 |
{ |
167 |
state_in->step = step_c; |
168 |
state_in->plainchar = *plainchar; |
169 |
return plainchar - plaintext_out; |
170 |
} |
171 |
fragment = (char) base64_decode_value (*codechar++); |
172 |
} |
173 |
while (fragment < 0); |
174 |
*plainchar++ |= (fragment & 0x03c) >> 2; |
175 |
*plainchar = (fragment & 0x003) << 6; |
176 |
case step_d: |
177 |
do |
178 |
{ |
179 |
if (codechar == code_in + length_in) |
180 |
{ |
181 |
state_in->step = step_d; |
182 |
state_in->plainchar = *plainchar; |
183 |
return plainchar - plaintext_out; |
184 |
} |
185 |
fragment = (char) base64_decode_value (*codechar++); |
186 |
} |
187 |
while (fragment < 0); |
188 |
*plainchar++ |= (fragment & 0x03f); |
189 |
} |
190 |
} |
191 |
/* control should not reach here */ |
192 |
return plainchar - plaintext_out; |
193 |
} |
194 |
} |