monotone

monotone Mtn Source Tree

Root/botan/base64.cpp

1/*************************************************
2* Base64 Encoder/Decoder Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/base64.h>
7#include <botan/charset.h>
8#include <algorithm>
9
10namespace Botan {
11
12/*************************************************
13* Base64_Encoder Constructor *
14*************************************************/
15Base64_Encoder::Base64_Encoder(bool breaks, u32bit length) :
16 line_length(breaks ? length : 0)
17 {
18 in.create(48);
19 out.create(4);
20
21 counter = position = 0;
22 }
23
24/*************************************************
25* Base64 Encoding Operation *
26*************************************************/
27void Base64_Encoder::encode(const byte in[3], byte out[4])
28 {
29 out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)];
30 out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)];
31 out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)];
32 out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )];
33 }
34
35/*************************************************
36* Encode and send a block *
37*************************************************/
38void Base64_Encoder::encode_and_send(const byte block[], u32bit length)
39 {
40 for(u32bit j = 0; j != length; j += 3)
41 {
42 encode(block + j, out);
43 do_output(out, 4);
44 }
45 }
46
47/*************************************************
48* Handle the output *
49*************************************************/
50void Base64_Encoder::do_output(const byte input[], u32bit length)
51 {
52 if(line_length == 0)
53 send(input, length);
54 else
55 {
56 u32bit remaining = length, offset = 0;
57 while(remaining)
58 {
59 u32bit sent = std::min(line_length - counter, remaining);
60 send(input + offset, sent);
61 counter += sent;
62 remaining -= sent;
63 offset += sent;
64 if(counter == line_length)
65 {
66 send('\n');
67 counter = 0;
68 }
69 }
70 }
71 }
72
73/*************************************************
74* Convert some data into Base64 *
75*************************************************/
76void Base64_Encoder::write(const byte input[], u32bit length)
77 {
78 in.copy(position, input, length);
79 if(position + length >= in.size())
80 {
81 encode_and_send(in, in.size());
82 input += (in.size() - position);
83 length -= (in.size() - position);
84 while(length >= in.size())
85 {
86 encode_and_send(input, in.size());
87 input += in.size();
88 length -= in.size();
89 }
90 in.copy(input, length);
91 position = 0;
92 }
93 position += length;
94 }
95
96/*************************************************
97* Flush buffers *
98*************************************************/
99void Base64_Encoder::end_msg()
100 {
101 u32bit start_of_last_block = 3 * (position / 3),
102 left_over = position % 3;
103 encode_and_send(in, start_of_last_block);
104
105 if(left_over)
106 {
107 SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over);
108
109 encode(remainder, out);
110
111 u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1;
112 while(empty_bits >= 8)
113 {
114 out[index--] = '=';
115 empty_bits -= 6;
116 }
117
118 do_output(out, 4);
119 }
120
121 // Monotone requires a trailing in newline in
122 // all cases, for crypto++ compatibility.
123 // if(counter && line_length)
124 // send('\n');
125 send('\n');
126
127 counter = position = 0;
128 }
129
130/*************************************************
131* Base64_Decoder Constructor *
132*************************************************/
133Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c)
134 {
135 in.create(48);
136 out.create(3);
137 position = 0;
138 }
139
140/*************************************************
141* Check if a character is a valid Base64 char *
142*************************************************/
143bool Base64_Decoder::is_valid(byte in)
144 {
145 return (BASE64_TO_BIN[in] != 0x80);
146 }
147
148/*************************************************
149* Base64 Decoding Operation *
150*************************************************/
151void Base64_Decoder::decode(const byte in[4], byte out[3])
152 {
153 out[0] = (byte)((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4));
154 out[1] = (byte)((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2));
155 out[2] = (byte)((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]]));
156 }
157
158/*************************************************
159* Decode and send a block *
160*************************************************/
161void Base64_Decoder::decode_and_send(const byte block[], u32bit length)
162 {
163 for(u32bit j = 0; j != length; j += 4)
164 {
165 decode(block + j, out);
166 send(out, 3);
167 }
168 }
169
170/*************************************************
171* Handle processing an invalid character *
172*************************************************/
173void Base64_Decoder::handle_bad_char(byte c)
174 {
175 if(c == '=' || checking == NONE)
176 return;
177
178 if((checking == IGNORE_WS) && Charset::is_space(c))
179 return;
180
181 throw Decoding_Error(
182 std::string("Base64_Decoder: Invalid base64 character '") + char(c) + "'"
183 );
184 }
185
186/*************************************************
187* Convert some data from Base64 *
188*************************************************/
189void Base64_Decoder::write(const byte input[], u32bit length)
190 {
191 for(u32bit j = 0; j != length; ++j)
192 {
193 if(is_valid(input[j]))
194 in[position++] = input[j];
195 else
196 handle_bad_char(input[j]);
197
198 if(position == in.size())
199 {
200 decode_and_send(in, in.size());
201 position = 0;
202 }
203 }
204 }
205
206/*************************************************
207* Flush buffers *
208*************************************************/
209void Base64_Decoder::end_msg()
210 {
211 if(position != 0)
212 {
213 u32bit start_of_last_block = 4 * (position / 4),
214 left_over = position % 4;
215 decode_and_send(in, start_of_last_block);
216
217 if(left_over)
218 {
219 SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over);
220 decode(remainder, out);
221 send(out, ((left_over == 1) ? (1) : (left_over - 1)));
222 }
223 }
224 position = 0;
225 }
226
227}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status