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