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"
14 #include "wx/base64.h"
17 wxBase64Encode(char *dst
, size_t dstLen
, const void *src_
, size_t srcLen
)
19 wxCHECK_MSG( src_
, wxCONV_FAILED
, _T("NULL input buffer") );
21 const unsigned char *src
= static_cast<const unsigned char *>(src_
);
23 static const char b64
[] =
24 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
29 // encode blocks of 3 bytes into 4 base64 characters
30 for ( ; srcLen
>= 3; srcLen
-= 3, src
+= 3 )
35 if ( encLen
> dstLen
)
38 *dst
++ = b64
[src
[0] >> 2];
39 *dst
++ = b64
[((src
[0] & 0x03) << 4) | ((src
[1] & 0xf0) >> 4)];
40 *dst
++ = b64
[((src
[1] & 0x0f) << 2) | ((src
[2] & 0xc0) >> 6)];
41 *dst
++ = b64
[src
[2] & 0x3f];
45 // finish with the remaining characters
51 if ( encLen
> dstLen
)
54 // we have definitely one and maybe two bytes remaining
55 unsigned char next
= srcLen
== 2 ? src
[1] : 0;
56 *dst
++ = b64
[src
[0] >> 2];
57 *dst
++ = b64
[((src
[0] & 0x03) << 4) | ((next
& 0xf0) >> 4)];
58 *dst
++ = srcLen
== 2 ? b64
[((next
& 0x0f) << 2)] : '=';
67 wxBase64Decode(void *dst_
, size_t dstLen
,
68 const char *src
, size_t srcLen
,
69 wxBase64DecodeMode mode
,
72 wxCHECK_MSG( src
, wxCONV_FAILED
, _T("NULL input buffer") );
74 unsigned char *dst
= static_cast<unsigned char *>(dst_
);
78 if ( srcLen
== wxNO_LEN
)
81 // this table contains the values, in base 64, of all valid characters and
82 // special values WSP or INV for white space and invalid characters
83 // respectively as well as a special PAD value for '='
91 static const unsigned char decode
[256] =
93 WSP
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,WSP
,WSP
,INV
,WSP
,WSP
,INV
,INV
,
94 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
95 WSP
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,076,INV
,INV
,INV
,077,
96 064,065,066,067,070,071,072,073,074,075,INV
,INV
,INV
,PAD
,INV
,INV
,
97 INV
,000,001,002,003,004,005,006,007,010,011,012,013,014,015,016,
98 017,020,021,022,023,024,025,026,027,030,031,INV
,INV
,INV
,INV
,INV
,
99 INV
,032,033,034,035,036,037,040,041,042,043,044,045,046,047,050,
100 051,052,053,054,055,056,057,060,061,062,063,INV
,INV
,INV
,INV
,INV
,
101 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
102 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
103 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
104 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,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
,
111 // we decode input by groups of 4 characters but things are complicated by
112 // the fact that there can be whitespace and other junk in it too so keep
113 // record of where exactly we're inside the current quartet in this var
115 unsigned char in
[4]; // current quartet
116 bool end
= false; // set when we find padding
117 size_t padLen
= 0; // length lost to padding
119 for ( p
= src
; srcLen
; p
++, srcLen
-- )
121 const unsigned char c
= decode
[static_cast<unsigned char>(*p
)];
125 if ( mode
== wxBase64DecodeMode_SkipWS
)
130 if ( mode
== wxBase64DecodeMode_Relaxed
)
133 // force the loop to stop and an error to be returned
139 // set the flag telling us that we're past the end now
142 // there can be either a single '=' at the end of a quartet or
143 // "==" in positions 2 and 3
149 else if ( (n
== 2) && (--srcLen
&& *++p
== '=') )
155 else // invalid padding
157 // force the loop terminate with an error
166 // nothing is allowed after the end so provoke error return
177 // got entire block, decode
178 decLen
+= 3 - padLen
;
181 if ( decLen
> dstLen
)
182 return wxCONV_FAILED
;
184 // undo the bit shifting done during encoding
185 *dst
++ = in
[0] << 2 | in
[1] >> 4;
186 *dst
++ = in
[1] << 4 | in
[2] >> 2;
187 *dst
++ = in
[2] << 6 | in
[3];
198 // notice that the error was on a previous position as we did one
199 // extra "p++" in the loop line after it
200 *posErr
= p
- src
- 1;
203 return wxCONV_FAILED
;
209 wxMemoryBuffer
wxBase64Decode(const char *src
,
211 wxBase64DecodeMode mode
,
215 wxCHECK_MSG( src
, buf
, _T("NULL input buffer") );
217 if ( srcLen
== wxNO_LEN
)
218 srcLen
= strlen(src
);
220 size_t len
= wxBase64DecodedSize(srcLen
);
221 len
= wxBase64Decode(buf
.GetWriteBuf(len
), len
, src
, srcLen
, mode
, posErr
);
222 if ( len
== wxCONV_FAILED
)
230 #endif // wxUSE_BASE64