Botan 3.3.0
Crypto and TLS for C&
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/filters.h>
9
10#include <botan/base64.h>
11#include <botan/exceptn.h>
12#include <algorithm>
13
14namespace Botan {
15
16/*
17* Base64_Encoder Constructor
18*/
19Base64_Encoder::Base64_Encoder(bool line_breaks, size_t line_length, bool trailing_newline) :
20 m_line_length(line_breaks ? line_length : 0),
21 m_trailing_newline(trailing_newline && line_breaks),
22 m_in(48),
23 m_out(64),
24 m_position(0),
25 m_out_position(0) {}
26
27/*
28* Encode and send a block
29*/
30void Base64_Encoder::encode_and_send(const uint8_t input[], size_t length, bool final_inputs) {
31 while(length) {
32 const size_t proc = std::min(length, m_in.size());
33
34 size_t consumed = 0;
35 size_t produced = base64_encode(cast_uint8_ptr_to_char(m_out.data()), input, proc, consumed, final_inputs);
36
37 do_output(m_out.data(), produced);
38
39 // FIXME: s/proc/consumed/?
40 input += proc;
41 length -= proc;
42 }
43}
44
45/*
46* Handle the output
47*/
48void Base64_Encoder::do_output(const uint8_t input[], size_t length) {
49 if(m_line_length == 0) {
50 send(input, length);
51 } else {
52 size_t remaining = length, offset = 0;
53 while(remaining) {
54 size_t sent = std::min(m_line_length - m_out_position, remaining);
55 send(input + offset, sent);
56 m_out_position += sent;
57 remaining -= sent;
58 offset += sent;
59 if(m_out_position == m_line_length) {
60 send('\n');
61 m_out_position = 0;
62 }
63 }
64 }
65}
66
67/*
68* Convert some data into Base64
69*/
70void Base64_Encoder::write(const uint8_t input[], size_t length) {
71 const size_t initial_fill = std::min(m_in.size() - m_position, length);
72 copy_mem(&m_in[m_position], input, initial_fill);
73
74 if(m_position + length >= m_in.size()) {
75 encode_and_send(m_in.data(), m_in.size());
76 input += (m_in.size() - m_position);
77 length -= (m_in.size() - m_position);
78 while(length >= m_in.size()) {
79 encode_and_send(input, m_in.size());
80 input += m_in.size();
81 length -= m_in.size();
82 }
83 copy_mem(m_in.data(), input, length);
84 m_position = 0;
85 }
86 m_position += length;
87}
88
89/*
90* Flush buffers
91*/
93 encode_and_send(m_in.data(), m_position, true);
94
95 if(m_trailing_newline || (m_out_position && m_line_length)) {
96 send('\n');
97 }
98
99 m_out_position = m_position = 0;
100}
101
102/*
103* Base64_Decoder Constructor
104*/
105Base64_Decoder::Base64_Decoder(Decoder_Checking c) : m_checking(c), m_in(64), m_out(48), m_position(0) {}
106
107/*
108* Convert some data from Base64
109*/
110void Base64_Decoder::write(const uint8_t input[], size_t length) {
111 while(length) {
112 size_t to_copy = std::min<size_t>(length, m_in.size() - m_position);
113 if(to_copy == 0) {
114 m_in.resize(m_in.size() * 2);
115 m_out.resize(m_out.size() * 2);
116 }
117 copy_mem(&m_in[m_position], input, to_copy);
118 m_position += to_copy;
119
120 size_t consumed = 0;
121 size_t written = base64_decode(
122 m_out.data(), cast_uint8_ptr_to_char(m_in.data()), m_position, consumed, false, m_checking != FULL_CHECK);
123
124 send(m_out, written);
125
126 if(consumed != m_position) {
127 copy_mem(m_in.data(), m_in.data() + consumed, m_position - consumed);
128 m_position = m_position - consumed;
129 } else {
130 m_position = 0;
131 }
132
133 length -= to_copy;
134 input += to_copy;
135 }
136}
137
138/*
139* Flush buffers
140*/
142 size_t consumed = 0;
143 size_t written = base64_decode(
144 m_out.data(), cast_uint8_ptr_to_char(m_in.data()), m_position, consumed, true, m_checking != FULL_CHECK);
145
146 send(m_out, written);
147
148 const bool not_full_bytes = consumed != m_position;
149
150 m_position = 0;
151
152 if(not_full_bytes) {
153 throw Invalid_Argument("Base64_Decoder: Input not full bytes");
154 }
155}
156
157} // namespace Botan
Base64_Decoder(Decoder_Checking checking=NONE)
Definition b64_filt.cpp:105
void end_msg() override
Definition b64_filt.cpp:141
void write(const uint8_t input[], size_t length) override
Definition b64_filt.cpp:110
void write(const uint8_t input[], size_t length) override
Definition b64_filt.cpp:70
Base64_Encoder(bool line_breaks=false, size_t line_length=72, bool trailing_newline=false)
Definition b64_filt.cpp:19
void end_msg() override
Definition b64_filt.cpp:92
virtual void send(const uint8_t in[], size_t length)
Definition filter.cpp:27
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition base64.cpp:146
size_t base64_decode(uint8_t out[], const char in[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
Definition base64.cpp:154
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition mem_ops.h:276
Decoder_Checking
Definition filter.h:165
@ FULL_CHECK
Definition filter.h:165
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146