1 /*
2 cencoder.c - c source to a base64 encoding algorithm implementation
3 
4 This is part of the libb64 project, and has been placed in the public domain.
5 For details, see http://sourceforge.net/projects/libb64
6 */
7 
8 #include "b64_encode.h"
9 
10 const int CHARS_PER_LINE = 56;
11 
base64_init_encodestate(base64_encodestate * state_in)12 void base64_init_encodestate(base64_encodestate* state_in)
13 {
14 	state_in->step = step_A;
15 	state_in->result = 0;
16 	state_in->stepcount = 0;
17 }
18 
base64_encode_value(char value_in)19 char base64_encode_value(char value_in)
20 {
21 	static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
22 	if (value_in > 63) return '=';
23 	return encoding[(int)value_in];
24 }
25 
base64_encode_block(const char * plaintext_in,int length_in,char * code_out,base64_encodestate * state_in)26 int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
27 {
28 	const char* plainchar = plaintext_in;
29 	const char* const plaintextend = plaintext_in + length_in;
30 	char* codechar = code_out;
31 	char result;
32 	char fragment;
33 
34 	result = state_in->result;
35 
36 	switch (state_in->step)
37 	{
38 		while (1)
39 		{
40 	case step_A:
41 			if (plainchar == plaintextend)
42 			{
43 				state_in->result = result;
44 				state_in->step = step_A;
45 				return codechar - code_out;
46 			}
47 			fragment = *plainchar++;
48 			result = (fragment & 0x0fc) >> 2;
49 			*codechar++ = base64_encode_value(result);
50 			result = (fragment & 0x003) << 4;
51 	case step_B:
52 			if (plainchar == plaintextend)
53 			{
54 				state_in->result = result;
55 				state_in->step = step_B;
56 				return codechar - code_out;
57 			}
58 			fragment = *plainchar++;
59 			result |= (fragment & 0x0f0) >> 4;
60 			*codechar++ = base64_encode_value(result);
61 			result = (fragment & 0x00f) << 2;
62 	case step_C:
63 			if (plainchar == plaintextend)
64 			{
65 				state_in->result = result;
66 				state_in->step = step_C;
67 				return codechar - code_out;
68 			}
69 			fragment = *plainchar++;
70 			result |= (fragment & 0x0c0) >> 6;
71 			*codechar++ = base64_encode_value(result);
72 			result  = (fragment & 0x03f) >> 0;
73 			*codechar++ = base64_encode_value(result);
74 
75 			++(state_in->stepcount);
76 			if (state_in->stepcount == CHARS_PER_LINE/4)
77 			{
78 				*codechar++ = ' ';
79 				state_in->stepcount = 0;
80 			}
81 		}
82 	}
83 	/* control should not reach here */
84 	return codechar - code_out;
85 }
86 
base64_encode_blockend(char * code_out,base64_encodestate * state_in)87 int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
88 {
89 	char* codechar = code_out;
90 
91 	switch (state_in->step)
92 	{
93 	case step_B:
94 		*codechar++ = base64_encode_value(state_in->result);
95 		*codechar++ = '=';
96 		*codechar++ = '=';
97 		break;
98 	case step_C:
99 		*codechar++ = base64_encode_value(state_in->result);
100 		*codechar++ = '=';
101 		break;
102 	case step_A:
103 		break;
104 	}
105 	*codechar++ = ' ';
106 
107 	return codechar - code_out;
108 }
109 
110