IBR-DTNSuite 0.6

ibrcommon/ibrcommon/data/Base64Stream.cpp

Go to the documentation of this file.
00001 /*
00002  * Base64Stream.cpp
00003  *
00004  *  Created on: 16.06.2011
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/data/Base64Stream.h"
00009 #include <sstream>
00010 #include <string.h>
00011 
00012 namespace ibrcommon
00013 {
00014         const char Base64Stream::encodeCharacterTable[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00015         const char Base64Stream::decodeCharacterTable[256] = {
00016         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
00017         ,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21
00018         ,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
00019         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00020         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
00021         ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00022         -1,-1,-1};
00023 
00024         Base64Stream::Base64Stream(std::ostream &stream, bool decode, const size_t linebreak, const size_t buffer)
00025          : std::ostream(this), _decode(decode), _stream(stream), data_buf_(new char[buffer]), data_size_(buffer), _base64_state(0), _char_counter(0), _base64_padding(0), _linebreak(linebreak)
00026         {
00027                 setp(data_buf_, data_buf_ + data_size_ - 1);
00028                 _base64_buf[0] = '\0';
00029                 _base64_buf[1] = '\0';
00030                 _base64_buf[2] = '\0';
00031                 _base64_buf[3] = '\0';
00032         }
00033 
00034         Base64Stream::~Base64Stream()
00035         {
00036                 delete[] data_buf_;
00037         }
00038 
00039         int Base64Stream::sync()
00040         {
00041                 int ret = std::char_traits<char>::eq_int_type(this->overflow(
00042                                 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
00043                                 : 0;
00044 
00045                 if (!_decode && (_base64_state > 0))
00046                 {
00047                         char buf[4];
00048 
00049                         // fill padding with zeros
00050                         for (int i = _base64_state; i < 3; i++) _base64_buf[i] = '\0';
00051 
00052                         buf[0] = (_base64_buf[0] & 0xfc) >> 2;
00053                         buf[1] = ((_base64_buf[0] & 0x03) << 4) + ((_base64_buf[1] & 0xf0) >> 4);
00054                         buf[2] = ((_base64_buf[1] & 0x0f) << 2) + ((_base64_buf[2] & 0xc0) >> 6);
00055                         buf[3] = _base64_buf[2] & 0x3f;
00056 
00057                         for (int i = 0; i < (_base64_state+1); i++)
00058                                 _stream << encodeCharacterTable[(int)buf[i]];
00059 
00060                         while(_base64_state++<3) _stream << '=';
00061                         _base64_state = 0;
00062                 }
00063 
00064                 return ret;
00065         }
00066 
00067         int Base64Stream::overflow(int c)
00068         {
00069                 char *ibegin = data_buf_;
00070                 char *iend = pptr();
00071 
00072                 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
00073                 {
00074                         *iend++ = std::char_traits<char>::to_char_type(c);
00075                 }
00076 
00077                 // mark the buffer as free
00078                 setp(data_buf_, data_buf_ + data_size_ - 1);
00079 
00080                 // available data
00081                 size_t len = (iend - ibegin);
00082 
00083                 // if there is nothing to send, just return
00084                 if (len == 0)
00085                 {
00086                         return std::char_traits<char>::not_eof(c);
00087                 }
00088 
00089                 // do cipher stuff
00090                 if (_decode)
00091                 {
00092                         for (size_t i = 0; i < len; i++)
00093                         {
00094                                 // skip newline chars
00095                                 if (ibegin[i] == '\n') continue;
00096 
00097                                 // put char into the decode buffer
00098                                 if (ibegin[i] == '=')
00099                                 {
00100                                         _base64_buf[_base64_state] = decodeCharacterTable[ (int)'\0' ];
00101                                         _base64_padding++;
00102                                 }
00103                                 else
00104                                 {
00105                                         _base64_buf[_base64_state] = decodeCharacterTable[ (int)ibegin[i] ];
00106                                 }
00107 
00108                                 if (_base64_state == 3)
00109                                 {
00110                                         _base64_buf[0] = (char)((_base64_buf[0] << 2) + ((_base64_buf[1] & 0x30) >> 4));
00111                                         _base64_buf[1] = (char)(((_base64_buf[1] & 0xf) << 4) + ((_base64_buf[2] & 0x3c) >> 2));
00112                                         _base64_buf[2] = (char)(((_base64_buf[2] & 0x3) << 6) + _base64_buf[3]);
00113 
00114                                         for (int j = 0; j < (3 - _base64_padding); j++)
00115                                         {
00116                                                 _stream << _base64_buf[j];
00117                                         }
00118 
00119                                         _base64_state = 0;
00120                                         _base64_padding = 0;
00121                                 }
00122                                 else
00123                                 {
00124                                         _base64_state++;
00125                                 }
00126                         }
00127                 }
00128                 else
00129                 {
00130                         for (size_t i = 0; i < len; i++)
00131                         {
00132                                 // put char into the encode buffer
00133                                 _base64_buf[_base64_state] = ibegin[i];
00134 
00135                                 if (_base64_state == 2)
00136                                 {
00137                                         _stream << encodeCharacterTable[(_base64_buf[0] & 0xfc) >> 2];
00138                                         _stream << encodeCharacterTable[((_base64_buf[0] & 0x03) << 4) + ((_base64_buf[1] & 0xf0) >> 4)];
00139                                         _stream << encodeCharacterTable[((_base64_buf[1] & 0x0f) << 2) + ((_base64_buf[2] & 0xc0) >> 6)];
00140                                         _stream << encodeCharacterTable[_base64_buf[2] & 0x3f];
00141 
00142                                         _base64_state = 0;
00143                                         _char_counter += 4;
00144 
00145                                         if (_char_counter >= _linebreak)
00146                                         {
00147                                                 _stream << '\n';
00148                                                 _char_counter = 0;
00149                                         }
00150                                 }
00151                                 else
00152                                 {
00153                                         _base64_state++;
00154                                 }
00155                         }
00156                 }
00157 
00158                 return std::char_traits<char>::not_eof(c);
00159         }
00160 }