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