monotone

monotone Mtn Source Tree

Root/botan/base64.cpp

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

Archive Download this file

Branches

Tags

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