Botan  1.11.15
src/lib/filters/codec_filt/b64_filt.cpp
Go to the documentation of this file.
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 }