|
IBR-DTNSuite 0.6
|
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 }