1
/*************************************************
2
* Base64 Encoder/Decoder Source File *
3
* (C) 1999-2007 The Botan Project *
4
*************************************************/
6
#include <botan/base64.h>
7
#include <botan/charset.h>
12
/*************************************************
13
* Base64_Encoder Constructor *
14
*************************************************/
15
Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) :
16
line_length(breaks ? length : 0), trailing_newline(t_n)
21
counter = position = 0;
24
/*************************************************
25
* Base64 Encoding Operation *
26
*************************************************/
27
void Base64_Encoder::encode(const byte in[3], byte out[4])
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) )];
35
/*************************************************
36
* Encode and send a block *
37
*************************************************/
38
void Base64_Encoder::encode_and_send(const byte block[], u32bit length)
40
for(u32bit j = 0; j != length; j += 3)
42
encode(block + j, out);
47
/*************************************************
49
*************************************************/
50
void Base64_Encoder::do_output(const byte input[], u32bit length)
56
u32bit remaining = length, offset = 0;
59
u32bit sent = std::min(line_length - counter, remaining);
60
send(input + offset, sent);
64
if(counter == line_length)
73
/*************************************************
74
* Convert some data into Base64 *
75
*************************************************/
76
void Base64_Encoder::write(const byte input[], u32bit length)
78
in.copy(position, input, length);
79
if(position + length >= in.size())
81
encode_and_send(in, in.size());
82
input += (in.size() - position);
83
length -= (in.size() - position);
84
while(length >= in.size())
86
encode_and_send(input, in.size());
90
in.copy(input, length);
96
/*************************************************
98
*************************************************/
99
void Base64_Encoder::end_msg()
101
u32bit start_of_last_block = 3 * (position / 3),
102
left_over = position % 3;
103
encode_and_send(in, start_of_last_block);
107
SecureBuffer<byte, 3> remainder(in + start_of_last_block, left_over);
109
encode(remainder, out);
111
u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1;
112
while(empty_bits >= 8)
121
if(trailing_newline || (counter && line_length))
124
counter = position = 0;
127
/*************************************************
128
* Base64_Decoder Constructor *
129
*************************************************/
130
Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c)
137
/*************************************************
138
* Check if a character is a valid Base64 char *
139
*************************************************/
140
bool Base64_Decoder::is_valid(byte in)
142
return (BASE64_TO_BIN[in] != 0x80);
145
/*************************************************
146
* Base64 Decoding Operation *
147
*************************************************/
148
void Base64_Decoder::decode(const byte in[4], byte out[3])
150
out[0] = (byte)((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4));
151
out[1] = (byte)((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2));
152
out[2] = (byte)((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]]));
155
/*************************************************
156
* Decode and send a block *
157
*************************************************/
158
void Base64_Decoder::decode_and_send(const byte block[], u32bit length)
160
for(u32bit j = 0; j != length; j += 4)
162
decode(block + j, out);
167
/*************************************************
168
* Handle processing an invalid character *
169
*************************************************/
170
void Base64_Decoder::handle_bad_char(byte c)
172
if(c == '=' || checking == NONE)
175
if((checking == IGNORE_WS) && Charset::is_space(c))
178
throw Decoding_Error(
179
std::string("Base64_Decoder: Invalid base64 character '") + (char)c + "'"
183
/*************************************************
184
* Convert some data from Base64 *
185
*************************************************/
186
void Base64_Decoder::write(const byte input[], u32bit length)
188
for(u32bit j = 0; j != length; ++j)
190
if(is_valid(input[j]))
191
in[position++] = input[j];
193
handle_bad_char(input[j]);
195
if(position == in.size())
197
decode_and_send(in, in.size());
203
/*************************************************
205
*************************************************/
206
void Base64_Decoder::end_msg()
210
u32bit start_of_last_block = 4 * (position / 4),
211
left_over = position % 4;
212
decode_and_send(in, start_of_last_block);
216
SecureBuffer<byte, 4> remainder(in + start_of_last_block, left_over);
217
decode(remainder, out);
218
send(out, ((left_over == 1) ? (1) : (left_over - 1)));