e440f378437f08b31e91953d3147d8855bdf99b6
[citadel.git] / libcitadel / lib / b64 / cencode.c
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/cencode.h"
9
10 void base64_init_encodestate(base64_encodestate* state_in)
11 {
12         state_in->step = step_A;
13         state_in->result = 0;
14 }
15
16 char base64_encode_value(char value_in)
17 {
18         static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
19         if (value_in > 63) return '=';
20         return encoding[(int)value_in];
21 }
22
23 int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
24 {
25         const char* plainchar = plaintext_in;
26         const char* const plaintextend = plaintext_in + length_in;
27         char* codechar = code_out;
28         char result;
29         char fragment;
30         
31         result = state_in->result;
32         
33         switch (state_in->step)
34         {
35                 while (1)
36                 {
37         case step_A:
38                         if (plainchar == plaintextend)
39                         {
40                                 state_in->result = result;
41                                 state_in->step = step_A;
42                                 return codechar - code_out;
43                         }
44                         fragment = *plainchar++;
45                         result = (fragment & 0x0fc) >> 2;
46                         *codechar++ = base64_encode_value(result);
47                         result = (fragment & 0x003) << 4;
48         case step_B:
49                         if (plainchar == plaintextend)
50                         {
51                                 state_in->result = result;
52                                 state_in->step = step_B;
53                                 return codechar - code_out;
54                         }
55                         fragment = *plainchar++;
56                         result |= (fragment & 0x0f0) >> 4;
57                         *codechar++ = base64_encode_value(result);
58                         result = (fragment & 0x00f) << 2;
59         case step_C:
60                         if (plainchar == plaintextend)
61                         {
62                                 state_in->result = result;
63                                 state_in->step = step_C;
64                                 return codechar - code_out;
65                         }
66                         fragment = *plainchar++;
67                         result |= (fragment & 0x0c0) >> 6;
68                         *codechar++ = base64_encode_value(result);
69                         result  = (fragment & 0x03f) >> 0;
70                         *codechar++ = base64_encode_value(result);
71                 }
72         }
73         /* control should not reach here */
74         return codechar - code_out;
75 }
76
77 int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
78 {
79         char* codechar = code_out;
80         
81         switch (state_in->step)
82         {
83         case step_B:
84                 *codechar++ = base64_encode_value(state_in->result);
85                 *codechar++ = '=';
86                 *codechar++ = '=';
87                 break;
88         case step_C:
89                 *codechar++ = base64_encode_value(state_in->result);
90                 *codechar++ = '=';
91                 break;
92         case step_A:
93                 break;
94         }
95         *codechar++ = '\n';
96         
97         return codechar - code_out;
98 }
99