Botan 3.9.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 <botan/mem_ops.h>
13#include <algorithm>
14
15namespace Botan {
16
17/*
18* Base64_Encoder Constructor
19*/
20Base64_Encoder::Base64_Encoder(bool line_breaks, size_t line_length, bool trailing_newline) :
21 m_line_length(line_breaks ? line_length : 0),
22 m_trailing_newline(trailing_newline && line_breaks),
23 m_in(48),
24 m_out(64) {}
25
26/*
27* Encode and send a block
28*/
29void Base64_Encoder::encode_and_send(const uint8_t input[], size_t length, bool final_inputs) {
30 while(length > 0) {
31 const size_t proc = std::min(length, m_in.size());
32
33 size_t consumed = 0;
34 size_t produced = base64_encode(cast_uint8_ptr_to_char(m_out.data()), input, proc, consumed, final_inputs);
35
36 do_output(m_out.data(), produced);
37
38 // FIXME: s/proc/consumed/?
39 input += proc;
40 length -= proc;
41 }
42}
43
44/*
45* Handle the output
46*/
47void Base64_Encoder::do_output(const uint8_t input[], size_t length) {
48 if(m_line_length == 0) {
49 send(input, length);
50 } else {
51 size_t remaining = length;
52 size_t offset = 0;
53 while(remaining > 0) {
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 > 0 && m_line_length > 0)) {
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) {}
106
107/*
108* Convert some data from Base64
109*/
110void Base64_Decoder::write(const uint8_t input[], size_t length) {
111 while(length > 0) {
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
BOTAN_FUTURE_EXPLICIT Base64_Encoder(bool line_breaks=false, size_t line_length=72, bool trailing_newline=false)
Definition b64_filt.cpp:20
void end_msg() override
Definition b64_filt.cpp:92
virtual void send(const uint8_t in[], size_t length)
Definition filter.cpp:30
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
Decoder_Checking
Definition filter.h:167
@ FULL_CHECK
Definition filter.h:167
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition base64.cpp:160
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:168
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition mem_ops.h:282