1 2 3 // base64.hpp 4 // Autor Konstantin Pilipchuk 5 // mailto:lostd@ukr.net 6 // 7 // 8 9 #if !defined(__BASE64_H_INCLUDED__) 10 #define __BASE64_H_INCLUDED__ 1 11 12 #ifndef MAKEDEPEND 13 # include <iostream> 14 # include <iterator> 15 #endif 16 17 static 18 int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 19 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', 20 '0','1','2','3','4','5','6','7','8','9', 21 '+','/' }; 22 23 24 #define _0000_0011 0x03 25 #define _1111_1100 0xFC 26 #define _1111_0000 0xF0 27 #define _0011_0000 0x30 28 #define _0011_1100 0x3C 29 #define _0000_1111 0x0F 30 #define _1100_0000 0xC0 31 #define _0011_1111 0x3F 32 33 #define _EQUAL_CHAR (-1) 34 #define _UNKNOWN_CHAR (-2) 35 36 #define _IOS_FAILBIT std::ios_base::failbit 37 #define _IOS_EOFBIT std::ios_base::eofbit 38 #define _IOS_BADBIT std::ios_base::badbit 39 #define _IOS_GOODBIT std::ios_base::goodbit 40 41 // TEMPLATE CLASS base64_put 42 template<class _E = char, class _Tr = std::char_traits<_E> > 43 class base64 44 { 45 public: 46 47 typedef unsigned char byte_t; 48 typedef _E char_type; 49 typedef _Tr traits_type; 50 51 // base64 requires max line length <= 72 characters 52 // you can fill end of line 53 // it may be crlf, crlfsp, noline or other class like it 54 55 56 struct crlf 57 { 58 template<class _OI> operatorcrlf59 _OI operator()(_OI _To) const{ 60 *_To = _Tr::to_char_type('\r'); ++_To; 61 *_To = _Tr::to_char_type('\n'); ++_To; 62 63 return (_To); 64 } 65 }; 66 67 68 struct crlfsp 69 { 70 template<class _OI> operatorcrlfsp71 _OI operator()(_OI _To) const{ 72 *_To = _Tr::to_char_type('\r'); ++_To; 73 *_To = _Tr::to_char_type('\n'); ++_To; 74 *_To = _Tr::to_char_type(' '); ++_To; 75 76 return (_To); 77 } 78 }; 79 80 struct noline 81 { 82 template<class _OI> operatornoline83 _OI operator()(_OI _To) const{ 84 return (_To); 85 } 86 }; 87 88 struct three2four 89 { zerothree2four90 void zero() 91 { 92 _data[0] = 0; 93 _data[1] = 0; 94 _data[2] = 0; 95 } 96 get_0three2four97 byte_t get_0() const 98 { 99 return _data[0]; 100 } get_1three2four101 byte_t get_1() const 102 { 103 return _data[1]; 104 } get_2three2four105 byte_t get_2() const 106 { 107 return _data[2]; 108 } 109 set_0three2four110 void set_0(byte_t _ch) 111 { 112 _data[0] = _ch; 113 } 114 set_1three2four115 void set_1(byte_t _ch) 116 { 117 _data[1] = _ch; 118 } 119 set_2three2four120 void set_2(byte_t _ch) 121 { 122 _data[2] = _ch; 123 } 124 125 // 0000 0000 1111 1111 2222 2222 126 // xxxx xxxx xxxx xxxx xxxx xxxx 127 // 0000 0011 1111 2222 2233 3333 128 b64_0three2four129 int b64_0() const {return (_data[0] & _1111_1100) >> 2;} b64_1three2four130 int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);} b64_2three2four131 int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);} b64_3three2four132 int b64_3() const {return (_data[2] & _0011_1111);} 133 b64_0three2four134 void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);} 135 b64_1three2four136 void b64_1(int _ch) { 137 _data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]); 138 _data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); } 139 b64_2three2four140 void b64_2(int _ch) { 141 _data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]); 142 _data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); } 143 b64_3three2four144 void b64_3(int _ch){ 145 _data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);} 146 147 private: 148 byte_t _data[3]; 149 150 }; 151 152 153 154 155 template<class _II, class _OI, class _State, class _Endline> put(_II _First,_II _Last,_OI _To,_State &,_Endline)156 _II put(_II _First, _II _Last, _OI _To, _State& /* _St */, _Endline /* _Endl */) const 157 { 158 three2four _3to4; 159 int line_octets = 0; 160 161 while(_First != _Last) 162 { 163 _3to4.zero(); 164 165 // ���� �� 3 ������� 166 _3to4.set_0(*_First); 167 _First++; 168 169 if(_First == _Last) 170 { 171 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; 172 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; 173 *_To = _Tr::to_char_type('='); ++_To; 174 *_To = _Tr::to_char_type('='); ++_To; 175 goto __end; 176 } 177 178 _3to4.set_1(*_First); 179 _First++; 180 181 if(_First == _Last) 182 { 183 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; 184 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; 185 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; 186 *_To = _Tr::to_char_type('='); ++_To; 187 goto __end; 188 } 189 190 _3to4.set_2(*_First); 191 _First++; 192 193 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; 194 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; 195 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; 196 *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To; 197 198 if(line_octets == 17) // base64 ��������� ����� ������ �� ����� 72 �������� 199 { 200 //_To = _Endl(_To); 201 *_To = '\n'; ++_To; 202 line_octets = 0; 203 } 204 else 205 ++line_octets; 206 } 207 208 __end: ; 209 210 return (_First); 211 212 } 213 214 215 template<class _II, class _OI, class _State> get(_II _First,_II _Last,_OI _To,_State & _St)216 _II get(_II _First, _II _Last, _OI _To, _State& _St) const 217 { 218 three2four _3to4; 219 int _Char; 220 221 while(_First != _Last) 222 { 223 224 // Take octet 225 _3to4.zero(); 226 227 // -- 0 -- 228 // Search next valid char... 229 while((_Char = _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR) 230 { 231 if(++_First == _Last) 232 { 233 _St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF 234 } 235 } 236 237 if(_Char == _EQUAL_CHAR){ 238 // Error! First character in octet can't be '=' 239 _St |= _IOS_FAILBIT; 240 return _First; 241 } 242 else 243 _3to4.b64_0(_Char); 244 245 246 // -- 1 -- 247 // Search next valid char... 248 while(++_First != _Last) 249 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 250 break; 251 252 if(_First == _Last) { 253 _St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF 254 return _First; 255 } 256 257 if(_Char == _EQUAL_CHAR){ 258 // Error! Second character in octet can't be '=' 259 _St |= _IOS_FAILBIT; 260 return _First; 261 } 262 else 263 _3to4.b64_1(_Char); 264 265 266 // -- 2 -- 267 // Search next valid char... 268 while(++_First != _Last) 269 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 270 break; 271 272 if(_First == _Last) { 273 // Error! Unexpected EOF. Must be '=' or base64 character 274 _St |= _IOS_FAILBIT|_IOS_EOFBIT; 275 return _First; 276 } 277 278 if(_Char == _EQUAL_CHAR){ 279 // OK! 280 _3to4.b64_2(0); 281 _3to4.b64_3(0); 282 283 // chek for EOF 284 if(++_First == _Last) 285 { 286 // Error! Unexpected EOF. Must be '='. Ignore it. 287 //_St |= _IOS_BADBIT|_IOS_EOFBIT; 288 _St |= _IOS_EOFBIT; 289 } 290 else 291 if(_getCharType(*_First) != _EQUAL_CHAR) 292 { 293 // Error! Must be '='. Ignore it. 294 //_St |= _IOS_BADBIT; 295 } 296 else 297 ++_First; // Skip '=' 298 299 // write 1 byte to output 300 *_To = (byte_t) _3to4.get_0(); 301 return _First; 302 } 303 else 304 _3to4.b64_2(_Char); 305 306 307 // -- 3 -- 308 // Search next valid char... 309 while(++_First != _Last) 310 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 311 break; 312 313 if(_First == _Last) { 314 // Unexpected EOF. It's error. But ignore it. 315 //_St |= _IOS_FAILBIT|_IOS_EOFBIT; 316 _St |= _IOS_EOFBIT; 317 318 return _First; 319 } 320 321 if(_Char == _EQUAL_CHAR) 322 { 323 // OK! 324 _3to4.b64_3(0); 325 326 // write to output 2 bytes 327 *_To = (byte_t) _3to4.get_0(); 328 *_To = (byte_t) _3to4.get_1(); 329 330 ++_First; // set position to next character 331 332 return _First; 333 } 334 else 335 _3to4.b64_3(_Char); 336 337 338 // write to output 3 bytes 339 *_To = (byte_t) _3to4.get_0(); 340 *_To = (byte_t) _3to4.get_1(); 341 *_To = (byte_t) _3to4.get_2(); 342 343 ++_First; 344 345 346 } // while(_First != _Last) 347 348 return (_First); 349 } 350 351 protected: 352 _getCharType(int _Ch)353 int _getCharType(int _Ch) const 354 { 355 if(_base64Chars[62] == _Ch) 356 return 62; 357 358 if(_base64Chars[63] == _Ch) 359 return 63; 360 361 if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch)) 362 return _Ch - _base64Chars[0]; 363 364 if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch)) 365 return _Ch - _base64Chars[26] + 26; 366 367 if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch)) 368 return _Ch - _base64Chars[52] + 52; 369 370 if(_Ch == _Tr::to_int_type('=')) 371 return _EQUAL_CHAR; 372 373 return _UNKNOWN_CHAR; 374 } 375 376 377 }; 378 379 380 #endif 381