1 // ---------------------------------------------------------------------------- 2 // 3 // flxmlrpc Copyright (c) 2015 by W1HKJ, Dave Freese <iam_w1hkj@w1hkj.com> 4 // 5 // XmlRpc++ Copyright (c) 2002-2008 by Chris Morley 6 // 7 // This file is part of fldigi 8 // 9 // flxmlrpc is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU Lesser General Public License as published by 11 // the Free Software Foundation; either version 3 of the License, or 12 // (at your option) any later version. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // ---------------------------------------------------------------------------- 17 18 #if !defined(__BASE64_H_INCLUDED__) 19 #define __BASE64_H_INCLUDED__ 1 20 21 #include <ios> // Corrects forward declarations issue c++11 22 #include <iosfwd> // Corrects forward declarations issue c++11 23 #include <iterator> 24 25 static 26 int _xmlrpc_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', 27 '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', 28 '0','1','2','3','4','5','6','7','8','9', 29 '+','/' }; 30 31 32 #define _0000_0011 0x03 33 #define _1111_1100 0xFC 34 #define _1111_0000 0xF0 35 #define _0011_0000 0x30 36 #define _0011_1100 0x3C 37 #define _0000_1111 0x0F 38 #define _1100_0000 0xC0 39 #define _0011_1111 0x3F 40 41 #define _EQUAL_CHAR (-1) 42 #define _UNKNOWN_CHAR (-2) 43 44 #define _IOS_FAILBIT std::ios_base::failbit 45 #define _IOS_EOFBIT std::ios_base::eofbit 46 #define _IOS_BADBIT std::ios_base::badbit 47 #define _IOS_GOODBIT std::ios_base::goodbit 48 49 // TEMPLATE CLASS xmlrpc_base64_put 50 template<class _E = char, class _Tr = std::char_traits<_E> > 51 class xmlrpc_base64 52 { 53 public: 54 55 typedef unsigned char byte_t; 56 typedef _E char_type; 57 typedef _Tr traits_type; 58 59 // xmlrpc_base64 requires max line length <= 72 characters 60 // you can fill end of line 61 // it may be crlf, crlfsp, noline or other class like it 62 63 64 struct crlf 65 { 66 template<class _OI> operatorcrlf67 _OI operator()(_OI _To) const{ 68 *_To = _Tr::to_char_type('\r'); ++_To; 69 *_To = _Tr::to_char_type('\n'); ++_To; 70 71 return (_To); 72 } 73 }; 74 75 76 struct crlfsp 77 { 78 template<class _OI> operatorcrlfsp79 _OI operator()(_OI _To) const{ 80 *_To = _Tr::to_char_type('\r'); ++_To; 81 *_To = _Tr::to_char_type('\n'); ++_To; 82 *_To = _Tr::to_char_type(' '); ++_To; 83 84 return (_To); 85 } 86 }; 87 88 struct noline 89 { 90 template<class _OI> operatornoline91 _OI operator()(_OI _To) const{ 92 return (_To); 93 } 94 }; 95 96 struct three2four 97 { zerothree2four98 void zero() 99 { 100 _data[0] = 0; 101 _data[1] = 0; 102 _data[2] = 0; 103 } 104 get_0three2four105 byte_t get_0() const 106 { 107 return _data[0]; 108 } get_1three2four109 byte_t get_1() const 110 { 111 return _data[1]; 112 } get_2three2four113 byte_t get_2() const 114 { 115 return _data[2]; 116 } 117 set_0three2four118 void set_0(byte_t _ch) 119 { 120 _data[0] = _ch; 121 } 122 set_1three2four123 void set_1(byte_t _ch) 124 { 125 _data[1] = _ch; 126 } 127 set_2three2four128 void set_2(byte_t _ch) 129 { 130 _data[2] = _ch; 131 } 132 133 // 0000 0000 1111 1111 2222 2222 134 // xxxx xxxx xxxx xxxx xxxx xxxx 135 // 0000 0011 1111 2222 2233 3333 136 b64_0three2four137 int b64_0() const {return (_data[0] & _1111_1100) >> 2;} b64_1three2four138 int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);} b64_2three2four139 int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);} b64_3three2four140 int b64_3() const {return (_data[2] & _0011_1111);} 141 b64_0three2four142 void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);} 143 b64_1three2four144 void b64_1(int _ch) { 145 _data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]); 146 _data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); } 147 b64_2three2four148 void b64_2(int _ch) { 149 _data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]); 150 _data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); } 151 b64_3three2four152 void b64_3(int _ch){ 153 _data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);} 154 155 private: 156 byte_t _data[3]; 157 158 }; 159 160 161 162 163 template<class _II, class _OI, class _State, class _Endline> put(_II _First,_II _Last,_OI _To,_State & _St,_Endline _Endl)164 _II put(_II _First, _II _Last, _OI _To, _State& _St, _Endline _Endl) const 165 { 166 three2four _3to4; 167 int line_octets = 0; 168 169 while(_First != _Last) 170 { 171 _3to4.zero(); 172 173 // ���� �� 3 ������� 174 _3to4.set_0(*_First); 175 _First++; 176 177 if(_First == _Last) 178 { 179 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_0()]); ++_To; 180 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_1()]); ++_To; 181 *_To = _Tr::to_char_type('='); ++_To; 182 *_To = _Tr::to_char_type('='); ++_To; 183 goto __end; 184 } 185 186 _3to4.set_1(*_First); 187 _First++; 188 189 if(_First == _Last) 190 { 191 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_0()]); ++_To; 192 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_1()]); ++_To; 193 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_2()]); ++_To; 194 *_To = _Tr::to_char_type('='); ++_To; 195 goto __end; 196 } 197 198 _3to4.set_2(*_First); 199 _First++; 200 201 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_0()]); ++_To; 202 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_1()]); ++_To; 203 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_2()]); ++_To; 204 *_To = _Tr::to_char_type(_xmlrpc_base64Chars[_3to4.b64_3()]); ++_To; 205 206 if(line_octets == 17) // xmlrpc_base64 ��������� ����� ������ �� ����� 72 �������� 207 { 208 //_To = _Endl(_To); 209 *_To = '\n'; ++_To; 210 line_octets = 0; 211 } 212 else 213 ++line_octets; 214 } 215 216 __end: ; 217 218 return (_First); 219 220 } 221 222 223 template<class _II, class _OI, class _State> get(_II _First,_II _Last,_OI _To,_State & _St)224 _II get(_II _First, _II _Last, _OI _To, _State& _St) const 225 { 226 three2four _3to4; 227 int _Char; 228 229 while(_First != _Last) 230 { 231 232 // Take octet 233 _3to4.zero(); 234 235 // -- 0 -- 236 // Search next valid char... 237 while((_Char = _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR) 238 { 239 if(++_First == _Last) 240 { 241 _St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF 242 } 243 } 244 245 if(_Char == _EQUAL_CHAR){ 246 // Error! First character in octet can't be '=' 247 _St |= _IOS_FAILBIT; 248 return _First; 249 } 250 else 251 _3to4.b64_0(_Char); 252 253 254 // -- 1 -- 255 // Search next valid char... 256 while(++_First != _Last) 257 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 258 break; 259 260 if(_First == _Last) { 261 _St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF 262 return _First; 263 } 264 265 if(_Char == _EQUAL_CHAR){ 266 // Error! Second character in octet can't be '=' 267 _St |= _IOS_FAILBIT; 268 return _First; 269 } 270 else 271 _3to4.b64_1(_Char); 272 273 274 // -- 2 -- 275 // Search next valid char... 276 while(++_First != _Last) 277 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 278 break; 279 280 if(_First == _Last) { 281 // Error! Unexpected EOF. Must be '=' or xmlrpc_base64 character 282 _St |= _IOS_FAILBIT|_IOS_EOFBIT; 283 return _First; 284 } 285 286 if(_Char == _EQUAL_CHAR){ 287 // OK! 288 _3to4.b64_2(0); 289 _3to4.b64_3(0); 290 291 // chek for EOF 292 if(++_First == _Last) 293 { 294 // Error! Unexpected EOF. Must be '='. Ignore it. 295 //_St |= _IOS_BADBIT|_IOS_EOFBIT; 296 _St |= _IOS_EOFBIT; 297 } 298 else 299 if(_getCharType(*_First) != _EQUAL_CHAR) 300 { 301 // Error! Must be '='. Ignore it. 302 //_St |= _IOS_BADBIT; 303 } 304 else 305 ++_First; // Skip '=' 306 307 // write 1 byte to output 308 *_To = (byte_t) _3to4.get_0(); 309 return _First; 310 } 311 else 312 _3to4.b64_2(_Char); 313 314 315 // -- 3 -- 316 // Search next valid char... 317 while(++_First != _Last) 318 if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) 319 break; 320 321 if(_First == _Last) { 322 // Unexpected EOF. It's error. But ignore it. 323 //_St |= _IOS_FAILBIT|_IOS_EOFBIT; 324 _St |= _IOS_EOFBIT; 325 326 return _First; 327 } 328 329 if(_Char == _EQUAL_CHAR) 330 { 331 // OK! 332 _3to4.b64_3(0); 333 334 // write to output 2 bytes 335 *_To = (byte_t) _3to4.get_0(); 336 *_To = (byte_t) _3to4.get_1(); 337 338 ++_First; // set position to next character 339 340 return _First; 341 } 342 else 343 _3to4.b64_3(_Char); 344 345 346 // write to output 3 bytes 347 *_To = (byte_t) _3to4.get_0(); 348 *_To = (byte_t) _3to4.get_1(); 349 *_To = (byte_t) _3to4.get_2(); 350 351 ++_First; 352 353 354 } // while(_First != _Last) 355 356 return (_First); 357 } 358 359 protected: 360 _getCharType(int _Ch)361 int _getCharType(int _Ch) const 362 { 363 if(_xmlrpc_base64Chars[62] == _Ch) 364 return 62; 365 366 if(_xmlrpc_base64Chars[63] == _Ch) 367 return 63; 368 369 if((_xmlrpc_base64Chars[0] <= _Ch) && (_xmlrpc_base64Chars[25] >= _Ch)) 370 return _Ch - _xmlrpc_base64Chars[0]; 371 372 if((_xmlrpc_base64Chars[26] <= _Ch) && (_xmlrpc_base64Chars[51] >= _Ch)) 373 return _Ch - _xmlrpc_base64Chars[26] + 26; 374 375 if((_xmlrpc_base64Chars[52] <= _Ch) && (_xmlrpc_base64Chars[61] >= _Ch)) 376 return _Ch - _xmlrpc_base64Chars[52] + 52; 377 378 if(_Ch == _Tr::to_int_type('=')) 379 return _EQUAL_CHAR; 380 381 return _UNKNOWN_CHAR; 382 } 383 384 385 }; 386 387 388 #endif 389