1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/base64.cpp
3 // Purpose: implementation of BASE64 encoding/decoding functions
4 // Author: Charles Reimers, Vadim Zeitlin
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 #include "wx/wxprec.h"
18 #include "wx/base64.h"
21 wxBase64Encode(char *dst
, size_t dstLen
, const void *src_
, size_t srcLen
)
23 wxCHECK_MSG( src_
, wxCONV_FAILED
, wxT("NULL input buffer") );
25 const unsigned char *src
= static_cast<const unsigned char *>(src_
);
27 static const char b64
[] =
28 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
33 // encode blocks of 3 bytes into 4 base64 characters
34 for ( ; srcLen
>= 3; srcLen
-= 3, src
+= 3 )
39 if ( encLen
> dstLen
)
42 *dst
++ = b64
[src
[0] >> 2];
43 *dst
++ = b64
[((src
[0] & 0x03) << 4) | ((src
[1] & 0xf0) >> 4)];
44 *dst
++ = b64
[((src
[1] & 0x0f) << 2) | ((src
[2] & 0xc0) >> 6)];
45 *dst
++ = b64
[src
[2] & 0x3f];
49 // finish with the remaining characters
55 if ( encLen
> dstLen
)
58 // we have definitely one and maybe two bytes remaining
59 unsigned char next
= srcLen
== 2 ? src
[1] : 0;
60 *dst
++ = b64
[src
[0] >> 2];
61 *dst
++ = b64
[((src
[0] & 0x03) << 4) | ((next
& 0xf0) >> 4)];
62 *dst
++ = srcLen
== 2 ? b64
[((next
& 0x0f) << 2)] : '=';
71 wxBase64Decode(void *dst_
, size_t dstLen
,
72 const char *src
, size_t srcLen
,
73 wxBase64DecodeMode mode
,
76 wxCHECK_MSG( src
, wxCONV_FAILED
, wxT("NULL input buffer") );
78 unsigned char *dst
= static_cast<unsigned char *>(dst_
);
82 if ( srcLen
== wxNO_LEN
)
85 // this table contains the values, in base 64, of all valid characters and
86 // special values WSP or INV for white space and invalid characters
87 // respectively as well as a special PAD value for '='
95 static const unsigned char decode
[256] =
97 WSP
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,WSP
,WSP
,INV
,WSP
,WSP
,INV
,INV
,
98 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
99 WSP
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,076,INV
,INV
,INV
,077,
100 064,065,066,067,070,071,072,073,074,075,INV
,INV
,INV
,PAD
,INV
,INV
,
101 INV
,000,001,002,003,004,005,006,007,010,011,012,013,014,015,016,
102 017,020,021,022,023,024,025,026,027,030,031,INV
,INV
,INV
,INV
,INV
,
103 INV
,032,033,034,035,036,037,040,041,042,043,044,045,046,047,050,
104 051,052,053,054,055,056,057,060,061,062,063,INV
,INV
,INV
,INV
,INV
,
105 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
106 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
107 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
108 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
109 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
110 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
111 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
112 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
115 // we decode input by groups of 4 characters but things are complicated by
116 // the fact that there can be whitespace and other junk in it too so keep
117 // record of where exactly we're inside the current quartet in this var
119 unsigned char in
[4]; // current quartet
120 bool end
= false; // set when we find padding
121 size_t padLen
= 0; // length lost to padding
123 for ( p
= src
; srcLen
; p
++, srcLen
-- )
125 const unsigned char c
= decode
[static_cast<unsigned char>(*p
)];
129 if ( mode
== wxBase64DecodeMode_SkipWS
)
134 if ( mode
== wxBase64DecodeMode_Relaxed
)
137 // force the loop to stop and an error to be returned
143 // set the flag telling us that we're past the end now
146 // there can be either a single '=' at the end of a quartet or
147 // "==" in positions 2 and 3
153 else if ( (n
== 2) && (--srcLen
&& *++p
== '=') )
159 else // invalid padding
161 // force the loop terminate with an error
170 // nothing is allowed after the end so provoke error return
181 // got entire block, decode
182 decLen
+= 3 - padLen
;
185 if ( decLen
> dstLen
)
186 return wxCONV_FAILED
;
188 // undo the bit shifting done during encoding
189 *dst
++ = in
[0] << 2 | in
[1] >> 4;
191 // be careful to not overwrite the output buffer with NUL pad
195 *dst
++ = in
[1] << 4 | in
[2] >> 2;
197 *dst
++ = in
[2] << 6 | in
[3];
209 // notice that the error was on a previous position as we did one
210 // extra "p++" in the loop line after it
211 *posErr
= p
- src
- 1;
214 return wxCONV_FAILED
;
220 wxMemoryBuffer
wxBase64Decode(const char *src
,
222 wxBase64DecodeMode mode
,
226 wxCHECK_MSG( src
, buf
, wxT("NULL input buffer") );
228 if ( srcLen
== wxNO_LEN
)
229 srcLen
= strlen(src
);
231 size_t len
= wxBase64DecodedSize(srcLen
);
232 len
= wxBase64Decode(buf
.GetWriteBuf(len
), len
, src
, srcLen
, mode
, posErr
);
233 if ( len
== wxCONV_FAILED
)
241 #endif // wxUSE_BASE64