IBR-DTNSuite
0.8
|
00001 /* 00002 * Base64Stream.cpp 00003 * 00004 * Created on: 16.06.2011 00005 * Author: morgenro 00006 */ 00007 00008 #include "ibrcommon/data/Base64Stream.h" 00009 #include "ibrcommon/data/Base64.h" 00010 #include <string.h> 00011 00012 namespace ibrcommon 00013 { 00014 Base64Stream::Base64Stream(std::ostream &stream, bool decode, const size_t linebreak, const size_t buffer) 00015 : 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) 00016 { 00017 setp(data_buf_, data_buf_ + data_size_ - 1); 00018 } 00019 00020 Base64Stream::~Base64Stream() 00021 { 00022 delete[] data_buf_; 00023 } 00024 00025 void Base64Stream::set_byte(char val) 00026 { 00027 switch (_base64_state) 00028 { 00029 case 0: 00030 _group.set_0(val); 00031 _base64_state++; 00032 break; 00033 00034 case 1: 00035 _group.set_1(val); 00036 _base64_state++; 00037 break; 00038 00039 case 2: 00040 _group.set_2(val); 00041 _base64_state++; 00042 break; 00043 } 00044 } 00045 00046 void Base64Stream::set_b64(char val) 00047 { 00048 switch (_base64_state) 00049 { 00050 case 0: 00051 _group.b64_0(val); 00052 _base64_state++; 00053 break; 00054 00055 case 1: 00056 _group.b64_1(val); 00057 _base64_state++; 00058 break; 00059 00060 case 2: 00061 _group.b64_2(val); 00062 _base64_state++; 00063 break; 00064 00065 case 3: 00066 _group.b64_3(val); 00067 _base64_state++; 00068 break; 00069 } 00070 } 00071 00072 int Base64Stream::sync() 00073 { 00074 int ret = std::char_traits<char>::eq_int_type(this->overflow( 00075 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1 00076 : 0; 00077 00078 if (!_decode && (_base64_state > 0)) 00079 { 00080 __flush_encoder__(); 00081 } 00082 00083 return ret; 00084 } 00085 00086 std::char_traits<char>::int_type Base64Stream::overflow(std::char_traits<char>::int_type c) 00087 { 00088 char *ibegin = data_buf_; 00089 char *iend = pptr(); 00090 00091 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof())) 00092 { 00093 *iend++ = std::char_traits<char>::to_char_type(c); 00094 } 00095 00096 // mark the buffer as free 00097 setp(data_buf_, data_buf_ + data_size_ - 1); 00098 00099 // available data 00100 size_t len = (iend - ibegin); 00101 00102 // if there is nothing to send, just return 00103 if (len == 0) 00104 { 00105 return std::char_traits<char>::not_eof(c); 00106 } 00107 00108 // for each byte... 00109 for (size_t i = 0; i < len; i++) 00110 { 00111 // do cipher stuff 00112 if (_decode) 00113 { 00114 const int c = Base64::getCharType( ibegin[i] ); 00115 00116 switch (c) 00117 { 00118 case Base64::UNKOWN_CHAR: 00119 // skip unknown chars 00120 continue; 00121 00122 case Base64::EQUAL_CHAR: 00123 { 00124 switch (_base64_state) 00125 { 00126 case 0: 00127 // error - first character can not be a '=' 00128 return std::char_traits<char>::eof(); 00129 00130 case 1: 00131 // error - second character can not be a '=' 00132 return std::char_traits<char>::eof(); 00133 00134 case 2: 00135 // only one byte left 00136 _base64_padding = 2; 00137 break; 00138 00139 case 3: 00140 // only one byte left 00141 if (_base64_padding == 0) 00142 { 00143 _base64_padding = 3; 00144 } 00145 break; 00146 } 00147 00148 set_b64(0); 00149 break; 00150 } 00151 00152 default: 00153 { 00154 // put char into the decode buffer 00155 set_b64(c); 00156 break; 00157 } 00158 } 00159 00160 // when finished 00161 if (_base64_state == 4) 00162 { 00163 if (_base64_padding == 0) 00164 { 00165 _stream.put( _group.get_0() ); 00166 _stream.put( _group.get_1() ); 00167 _stream.put( _group.get_2() ); 00168 } 00169 else if (_base64_padding == 3) 00170 { 00171 _stream.put( _group.get_0() ); 00172 _stream.put( _group.get_1() ); 00173 } 00174 else if (_base64_padding == 2) 00175 { 00176 _stream.put( _group.get_0() ); 00177 } 00178 00179 _base64_state = 0; 00180 _base64_padding = 0; 00181 _group.zero(); 00182 } 00183 } 00184 else 00185 { 00186 // put char into the encode buffer 00187 set_byte(ibegin[i]); 00188 00189 if (_base64_state == 3) 00190 { 00191 __flush_encoder__(); 00192 _group.zero(); 00193 } 00194 } 00195 } 00196 00197 return std::char_traits<char>::not_eof(c); 00198 } 00199 00200 void Base64Stream::__flush_encoder__() 00201 { 00202 switch (_base64_state) 00203 { 00204 default: 00205 break; 00206 00207 case 1: 00208 _stream.put( Base64::encodeCharacterTable[ _group.b64_0() ] ); 00209 _stream.put( Base64::encodeCharacterTable[ _group.b64_1() ] ); 00210 _stream.put( '=' ); 00211 _stream.put( '=' ); 00212 break; 00213 00214 case 2: 00215 _stream.put( Base64::encodeCharacterTable[ _group.b64_0() ] ); 00216 _stream.put( Base64::encodeCharacterTable[ _group.b64_1() ] ); 00217 _stream.put( Base64::encodeCharacterTable[ _group.b64_2() ] ); 00218 _stream.put( '=' ); 00219 break; 00220 00221 case 3: 00222 _stream.put( Base64::encodeCharacterTable[ _group.b64_0() ] ); 00223 _stream.put( Base64::encodeCharacterTable[ _group.b64_1() ] ); 00224 _stream.put( Base64::encodeCharacterTable[ _group.b64_2() ] ); 00225 _stream.put( Base64::encodeCharacterTable[ _group.b64_3() ] ); 00226 break; 00227 } 00228 00229 _base64_state = 0; 00230 _char_counter += 4; 00231 00232 if (_char_counter >= _linebreak) 00233 { 00234 _stream.put('\n'); 00235 _char_counter = 0; 00236 } 00237 } 00238 }