Botan
1.11.15
|
00001 /* 00002 * Base64 Encoder/Decoder 00003 * (C) 1999-2010 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/b64_filt.h> 00009 #include <botan/base64.h> 00010 #include <botan/charset.h> 00011 #include <botan/exceptn.h> 00012 #include <algorithm> 00013 00014 namespace Botan { 00015 00016 /* 00017 * Base64_Encoder Constructor 00018 */ 00019 Base64_Encoder::Base64_Encoder(bool breaks, size_t length, bool t_n) : 00020 line_length(breaks ? length : 0), 00021 trailing_newline(t_n && breaks), 00022 in(48), 00023 out(64), 00024 position(0), 00025 out_position(0) 00026 { 00027 } 00028 00029 /* 00030 * Encode and send a block 00031 */ 00032 void Base64_Encoder::encode_and_send(const byte input[], size_t length, 00033 bool final_inputs) 00034 { 00035 while(length) 00036 { 00037 const size_t proc = std::min(length, in.size()); 00038 00039 size_t consumed = 0; 00040 size_t produced = base64_encode(reinterpret_cast<char*>(&out[0]), input, 00041 proc, consumed, final_inputs); 00042 00043 do_output(&out[0], produced); 00044 00045 // FIXME: s/proc/consumed/? 00046 input += proc; 00047 length -= proc; 00048 } 00049 } 00050 00051 /* 00052 * Handle the output 00053 */ 00054 void Base64_Encoder::do_output(const byte input[], size_t length) 00055 { 00056 if(line_length == 0) 00057 send(input, length); 00058 else 00059 { 00060 size_t remaining = length, offset = 0; 00061 while(remaining) 00062 { 00063 size_t sent = std::min(line_length - out_position, remaining); 00064 send(input + offset, sent); 00065 out_position += sent; 00066 remaining -= sent; 00067 offset += sent; 00068 if(out_position == line_length) 00069 { 00070 send('\n'); 00071 out_position = 0; 00072 } 00073 } 00074 } 00075 } 00076 00077 /* 00078 * Convert some data into Base64 00079 */ 00080 void Base64_Encoder::write(const byte input[], size_t length) 00081 { 00082 buffer_insert(in, position, input, length); 00083 if(position + length >= in.size()) 00084 { 00085 encode_and_send(&in[0], in.size()); 00086 input += (in.size() - position); 00087 length -= (in.size() - position); 00088 while(length >= in.size()) 00089 { 00090 encode_and_send(input, in.size()); 00091 input += in.size(); 00092 length -= in.size(); 00093 } 00094 copy_mem(&in[0], input, length); 00095 position = 0; 00096 } 00097 position += length; 00098 } 00099 00100 /* 00101 * Flush buffers 00102 */ 00103 void Base64_Encoder::end_msg() 00104 { 00105 encode_and_send(&in[0], position, true); 00106 00107 if(trailing_newline || (out_position && line_length)) 00108 send('\n'); 00109 00110 out_position = position = 0; 00111 } 00112 00113 /* 00114 * Base64_Decoder Constructor 00115 */ 00116 Base64_Decoder::Base64_Decoder(Decoder_Checking c) : 00117 checking(c), in(64), out(48), position(0) 00118 { 00119 } 00120 00121 /* 00122 * Convert some data from Base64 00123 */ 00124 void Base64_Decoder::write(const byte input[], size_t length) 00125 { 00126 while(length) 00127 { 00128 size_t to_copy = std::min<size_t>(length, in.size() - position); 00129 copy_mem(&in[position], input, to_copy); 00130 position += to_copy; 00131 00132 size_t consumed = 0; 00133 size_t written = base64_decode(&out[0], 00134 reinterpret_cast<const char*>(&in[0]), 00135 position, 00136 consumed, 00137 false, 00138 checking != FULL_CHECK); 00139 00140 send(out, written); 00141 00142 if(consumed != position) 00143 { 00144 copy_mem(&in[0], &in[consumed], position - consumed); 00145 position = position - consumed; 00146 } 00147 else 00148 position = 0; 00149 00150 length -= to_copy; 00151 input += to_copy; 00152 } 00153 } 00154 00155 /* 00156 * Flush buffers 00157 */ 00158 void Base64_Decoder::end_msg() 00159 { 00160 size_t consumed = 0; 00161 size_t written = base64_decode(&out[0], 00162 reinterpret_cast<const char*>(&in[0]), 00163 position, 00164 consumed, 00165 true, 00166 checking != FULL_CHECK); 00167 00168 send(out, written); 00169 00170 const bool not_full_bytes = consumed != position; 00171 00172 position = 0; 00173 00174 if(not_full_bytes) 00175 throw std::invalid_argument("Base64_Decoder: Input not full bytes"); 00176 } 00177 00178 }