Botan  2.1.0
Crypto and TLS for C++11
b64_filt.cpp
Go to the documentation of this file.
1 /*
2 * Base64 Encoder/Decoder
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/b64_filt.h>
9 #include <botan/base64.h>
10 #include <botan/charset.h>
11 #include <botan/exceptn.h>
12 #include <algorithm>
13 
14 namespace Botan {
15 
16 /*
17 * Base64_Encoder Constructor
18 */
19 Base64_Encoder::Base64_Encoder(bool breaks, size_t length, bool t_n) :
20  m_line_length(breaks ? length : 0),
21  m_trailing_newline(t_n && breaks),
22  m_in(48),
23  m_out(64),
24  m_position(0),
25  m_out_position(0)
26  {
27  }
28 
29 /*
30 * Encode and send a block
31 */
32 void Base64_Encoder::encode_and_send(const uint8_t input[], size_t length,
33  bool final_inputs)
34  {
35  while(length)
36  {
37  const size_t proc = std::min(length, m_in.size());
38 
39  size_t consumed = 0;
40  size_t produced = base64_encode(reinterpret_cast<char*>(m_out.data()), input,
41  proc, consumed, final_inputs);
42 
43  do_output(m_out.data(), produced);
44 
45  // FIXME: s/proc/consumed/?
46  input += proc;
47  length -= proc;
48  }
49  }
50 
51 /*
52 * Handle the output
53 */
54 void Base64_Encoder::do_output(const uint8_t input[], size_t length)
55  {
56  if(m_line_length == 0)
57  send(input, length);
58  else
59  {
60  size_t remaining = length, offset = 0;
61  while(remaining)
62  {
63  size_t sent = std::min(m_line_length - m_out_position, remaining);
64  send(input + offset, sent);
65  m_out_position += sent;
66  remaining -= sent;
67  offset += sent;
68  if(m_out_position == m_line_length)
69  {
70  send('\n');
71  m_out_position = 0;
72  }
73  }
74  }
75  }
76 
77 /*
78 * Convert some data into Base64
79 */
80 void Base64_Encoder::write(const uint8_t input[], size_t length)
81  {
82  buffer_insert(m_in, m_position, input, length);
83  if(m_position + length >= m_in.size())
84  {
85  encode_and_send(m_in.data(), m_in.size());
86  input += (m_in.size() - m_position);
87  length -= (m_in.size() - m_position);
88  while(length >= m_in.size())
89  {
90  encode_and_send(input, m_in.size());
91  input += m_in.size();
92  length -= m_in.size();
93  }
94  copy_mem(m_in.data(), input, length);
95  m_position = 0;
96  }
97  m_position += length;
98  }
99 
100 /*
101 * Flush buffers
102 */
104  {
105  encode_and_send(m_in.data(), m_position, true);
106 
107  if(m_trailing_newline || (m_out_position && m_line_length))
108  send('\n');
109 
110  m_out_position = m_position = 0;
111  }
112 
113 /*
114 * Base64_Decoder Constructor
115 */
117  m_checking(c), m_in(64), m_out(48), m_position(0)
118  {
119  }
120 
121 /*
122 * Convert some data from Base64
123 */
124 void Base64_Decoder::write(const uint8_t input[], size_t length)
125  {
126  while(length)
127  {
128  size_t to_copy = std::min<size_t>(length, m_in.size() - m_position);
129  if(to_copy == 0)
130  {
131  m_in.resize(m_in.size()*2);
132  m_out.resize(m_out.size()*2);
133  }
134  copy_mem(&m_in[m_position], input, to_copy);
135  m_position += to_copy;
136 
137  size_t consumed = 0;
138  size_t written = base64_decode(m_out.data(),
139  reinterpret_cast<const char*>(m_in.data()),
140  m_position,
141  consumed,
142  false,
143  m_checking != FULL_CHECK);
144 
145  send(m_out, written);
146 
147  if(consumed != m_position)
148  {
149  copy_mem(m_in.data(), m_in.data() + consumed, m_position - consumed);
150  m_position = m_position - consumed;
151  }
152  else
153  m_position = 0;
154 
155  length -= to_copy;
156  input += to_copy;
157  }
158  }
159 
160 /*
161 * Flush buffers
162 */
164  {
165  size_t consumed = 0;
166  size_t written = base64_decode(m_out.data(),
167  reinterpret_cast<const char*>(m_in.data()),
168  m_position,
169  consumed,
170  true,
171  m_checking != FULL_CHECK);
172 
173  send(m_out, written);
174 
175  const bool not_full_bytes = consumed != m_position;
176 
177  m_position = 0;
178 
179  if(not_full_bytes)
180  throw Invalid_Argument("Base64_Decoder: Input not full bytes");
181  }
182 
183 }
Base64_Encoder(bool breaks=false, size_t length=72, bool t_n=false)
Definition: b64_filt.cpp:19
void end_msg() override
Definition: b64_filt.cpp:103
size_t base64_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition: base64.cpp:100
Base64_Decoder(Decoder_Checking checking=NONE)
Definition: b64_filt.cpp:116
virtual void send(const uint8_t in[], size_t length)
Definition: filter.cpp:27
void write(const uint8_t input[], size_t length) override
Definition: b64_filt.cpp:80
void end_msg() override
Definition: b64_filt.cpp:163
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Definition: alg_id.cpp:13
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:35
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:133
T min(T a, T b)
Definition: ct_utils.h:180
void write(const uint8_t input[], size_t length) override
Definition: b64_filt.cpp:124
Decoder_Checking
Definition: filter.h:179