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