BRL-CAD
b64.c
Go to the documentation of this file.
1 /*
2  b64.c - c source to a base64 encoding algorithm implementation
3 
4  This is a reworked version of the C encoder/decoder from the libb64
5  project, and has been placed in the public domain.
6  For details, see http://sourceforge.net/projects/libb64
7  */
8 
9 #include "common.h"
10 
11 #include <stdlib.h>
12 #include <math.h>
13 #include <string.h>
14 
15 #include "bu/cv.h"
16 #include "bu/malloc.h"
17 
18 typedef enum {
21 
22 typedef enum {
25 
26 
27 typedef struct {
29  signed char result;
30  int stepcount;
32 
33 typedef struct {
35  signed char plainchar;
37 
38 const int CHARS_PER_LINE = 72;
39 
40 HIDDEN
42 {
43  state_in->step = step_A;
44  state_in->result = 0;
45  state_in->stepcount = 0;
46 }
47 
48 HIDDEN
49 signed char bu_b64_encode_value(signed char value_in)
50 {
51  static const signed char* encoding = (const signed char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
52  if (value_in > 63) return '=';
53  return encoding[(int)value_in];
54 }
55 
56 HIDDEN
57 int bu_b64_encode_block_internal(const signed char* plaintext_in, size_t length_in, signed char* code_out, bu_b64_encodestate* state_in)
58 {
59  const signed char* plainchar = plaintext_in;
60  const signed char* const plaintextend = plaintext_in + length_in;
61  signed char* codechar = code_out;
62  signed char result;
63  signed char fragment;
64 
65  result = state_in->result;
66 
67  switch (state_in->step) {
68  while (1) {
69  case step_A:
70  if (plainchar == plaintextend) {
71  state_in->result = result;
72  state_in->step = step_A;
73  return codechar - code_out;
74  }
75  fragment = *plainchar++;
76  result = (fragment & 0x0fc) >> 2;
77  *codechar++ = bu_b64_encode_value(result);
78  result = (fragment & 0x003) << 4;
79  case step_B:
80  if (plainchar == plaintextend) {
81  state_in->result = result;
82  state_in->step = step_B;
83  return codechar - code_out;
84  }
85  fragment = *plainchar++;
86  result |= (fragment & 0x0f0) >> 4;
87  *codechar++ = bu_b64_encode_value(result);
88  result = (fragment & 0x00f) << 2;
89  case step_C:
90  if (plainchar == plaintextend) {
91  state_in->result = result;
92  state_in->step = step_C;
93  return codechar - code_out;
94  }
95  fragment = *plainchar++;
96  result |= (fragment & 0x0c0) >> 6;
97  *codechar++ = bu_b64_encode_value(result);
98  result = (fragment & 0x03f) >> 0;
99  *codechar++ = bu_b64_encode_value(result);
100 
101  ++(state_in->stepcount);
102  if (state_in->stepcount == CHARS_PER_LINE/4) {
103  *codechar++ = '\n';
104  state_in->stepcount = 0;
105  }
106  }
107  }
108  /* control should not reach here */
109  return codechar - code_out;
110 }
111 
112 HIDDEN
113 int bu_b64_encode_blockend(signed char* code_out, bu_b64_encodestate* state_in)
114 {
115  signed char* codechar = code_out;
116 
117  switch (state_in->step) {
118  case step_B:
119  *codechar++ = bu_b64_encode_value(state_in->result);
120  *codechar++ = '=';
121  *codechar++ = '=';
122  break;
123  case step_C:
124  *codechar++ = bu_b64_encode_value(state_in->result);
125  *codechar++ = '=';
126  break;
127  case step_A:
128  break;
129  }
130  *codechar++ = '\n';
131 
132  return codechar - code_out;
133 }
134 
135 HIDDEN
136 int bu_b64_decode_value(signed char value_in)
137 {
138  static const signed 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};
139  static const signed char decoding_size = sizeof(decoding);
140  value_in -= 43;
141  if (value_in < 0 || value_in >= decoding_size) return -1;
142  return decoding[(int)value_in];
143 }
144 
145 HIDDEN
147 {
148  state_in->step = step_a;
149  state_in->plainchar = 0;
150 }
151 
152 HIDDEN
153 int bu_b64_decode_block_internal(const signed char* code_in, const size_t length_in, signed char* plaintext_out, bu_b64_decodestate* state_in)
154 {
155  const signed char* codechar = code_in;
156  signed char* plainchar = plaintext_out;
157  signed char fragment;
158 
159  *plainchar = state_in->plainchar;
160 
161  switch (state_in->step) {
162  while (1) {
163  case step_a:
164  do {
165  if (codechar == code_in+length_in) {
166  state_in->step = step_a;
167  state_in->plainchar = *plainchar;
168  return plainchar - plaintext_out;
169  }
170  fragment = (signed char)bu_b64_decode_value(*codechar++);
171  } while (fragment < 0);
172  *plainchar = (fragment & 0x03f) << 2;
173  case step_b:
174  do {
175  if (codechar == code_in+length_in) {
176  state_in->step = step_b;
177  state_in->plainchar = *plainchar;
178  return plainchar - plaintext_out;
179  }
180  fragment = (signed char)bu_b64_decode_value(*codechar++);
181  } while (fragment < 0);
182  *plainchar++ |= (fragment & 0x030) >> 4;
183  *plainchar = (fragment & 0x00f) << 4;
184  case step_c:
185  do {
186  if (codechar == code_in+length_in) {
187  state_in->step = step_c;
188  state_in->plainchar = *plainchar;
189  return plainchar - plaintext_out;
190  }
191  fragment = (signed char)bu_b64_decode_value(*codechar++);
192  } while (fragment < 0);
193  *plainchar++ |= (fragment & 0x03c) >> 2;
194  *plainchar = (fragment & 0x003) << 6;
195  case step_d:
196  do {
197  if (codechar == code_in+length_in) {
198  state_in->step = step_d;
199  state_in->plainchar = *plainchar;
200  return plainchar - plaintext_out;
201  }
202  fragment = (signed char)bu_b64_decode_value(*codechar++);
203  } while (fragment < 0);
204  *plainchar++ |= (fragment & 0x03f);
205  }
206  }
207  /* control should not reach here */
208  return plainchar - plaintext_out;
209 }
210 
211 signed char *
212 bu_b64_encode_block(const signed char *input, size_t len)
213 {
214  /* Calculate size of output needed and calloc the memory */
215  signed char *output = (signed char *)bu_calloc((((int)(4*len/3)) + 4), 8, "Calloc b64 buffer");
216  signed char *c = output;
217  int cnt = 0;
219 
220  /*---------- START ENCODING ----------*/
221  /* initialise the encoder state */
223  /* gather data from the input and send it to the output */
224  cnt = bu_b64_encode_block_internal(input, len, c, &s);
225  c += cnt;
226  /* since we have encoded all of the input string we intend
227  * to encode, we know that there is no more input data;
228  * finalise the encoding */
229  cnt = bu_b64_encode_blockend(c, &s);
230  c += cnt;
231  /*---------- STOP ENCODING ----------*/
232 
233  /* we want to print the encoded data, so null-terminate it: */
234  *c = '\0';
235 
236  return output;
237 }
238 
239 signed char *
240 bu_b64_encode(const signed char *input)
241 {
242  return bu_b64_encode_block(input, strlen((const char *)input));
243 }
244 
245 
246 int
247 bu_b64_decode_block(signed char **output, const signed char *input, size_t len)
248 {
249  /* Calculate size of output needed and calloc the memory */
250  int cnt = 0;
251  signed char* c;
253  if (!output) return -1;
254  *output = (signed char *)bu_calloc(((int)(3*len/4) + 4), 8, "Calloc b64 decoding buffer");
255  c = *output;
256 
257  /*---------- START DECODING ----------*/
258  /* initialise the decoder state */
260  /* decode the input data */
261  cnt = bu_b64_decode_block_internal(input, len, c, &s);
262  c += cnt;
263  /* note: there is no bu_b64_decode_blockend! */
264  /*---------- STOP DECODING ----------*/
265 
266  /* we want to print the decoded data, so null-terminate it: */
267  *c = '\0';
268 
269  return cnt;
270 }
271 
272 
273 int
274 bu_b64_decode(signed char **output, const signed char *input)
275 {
276  return bu_b64_decode_block(output, input, strlen((const char *)input));
277 }
278 
279 
280 
281 /*
282  * Local Variables:
283  * mode: C
284  * tab-width: 8
285  * indent-tabs-mode: t
286  * c-file-style: "stroustrup"
287  * End:
288  * ex: shiftwidth=4 tabstop=8
289  */
Definition: b64.c:23
if lu s
Definition: nmg_mod.c:3860
Definition: b64.c:23
HIDDEN int bu_b64_decode_value(signed char value_in)
Definition: b64.c:136
int bu_b64_decode(signed char **output, const signed char *input)
Definition: b64.c:274
Definition: b64.c:19
Header file for the BRL-CAD common definitions.
HIDDEN int bu_b64_encode_block_internal(const signed char *plaintext_in, size_t length_in, signed char *code_out, bu_b64_encodestate *state_in)
Definition: b64.c:57
Definition: b64.c:19
HIDDEN int bu_b64_encode_blockend(signed char *code_out, bu_b64_encodestate *state_in)
Definition: b64.c:113
#define HIDDEN
Definition: common.h:86
HIDDEN signed char bu_b64_encode_value(signed char value_in)
Definition: b64.c:49
signed char result
Definition: b64.c:29
int bu_b64_decode_block(signed char **output, const signed char *input, size_t len)
Definition: b64.c:247
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
const int CHARS_PER_LINE
Definition: b64.c:38
int stepcount
Definition: b64.c:30
HIDDEN void bu_b64_init_decodestate(bu_b64_decodestate *state_in)
Definition: b64.c:146
Definition: b64.c:23
signed char * bu_b64_encode(const signed char *input)
Definition: b64.c:240
bu_b64_encodestep
Definition: b64.c:18
bu_b64_decodestep
Definition: b64.c:22
bu_b64_encodestep step
Definition: b64.c:28
signed char * bu_b64_encode_block(const signed char *input, size_t len)
Definition: b64.c:212
Definition: b64.c:19
bn_poly_t output[3]
Definition: bn_poly_add.c:36
HIDDEN int bu_b64_decode_block_internal(const signed char *code_in, const size_t length_in, signed char *plaintext_out, bu_b64_decodestate *state_in)
Definition: b64.c:153
bu_b64_decodestep step
Definition: b64.c:34
Definition: b64.c:23
HIDDEN void bu_b64_init_encodestate(bu_b64_encodestate *state_in)
Definition: b64.c:41
signed char plainchar
Definition: b64.c:35