1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/base64.cpp
3 // Purpose: implementation of BASE64 encoding/decoding functions
4 // Author: Charles Reimers, Vadim Zeitlin
6 // Licence: wxWindows licence
7 ///////////////////////////////////////////////////////////////////////////////
17 #include "wx/base64.h"
20 wxBase64Encode(char *dst
, size_t dstLen
, const void *src_
, size_t srcLen
)
22 wxCHECK_MSG( src_
, wxCONV_FAILED
, wxT("NULL input buffer") );
24 const unsigned char *src
= static_cast<const unsigned char *>(src_
);
26 static const char b64
[] =
27 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32 // encode blocks of 3 bytes into 4 base64 characters
33 for ( ; srcLen
>= 3; srcLen
-= 3, src
+= 3 )
38 if ( encLen
> dstLen
)
41 *dst
++ = b64
[src
[0] >> 2];
42 *dst
++ = b64
[((src
[0] & 0x03) << 4) | ((src
[1] & 0xf0) >> 4)];
43 *dst
++ = b64
[((src
[1] & 0x0f) << 2) | ((src
[2] & 0xc0) >> 6)];
44 *dst
++ = b64
[src
[2] & 0x3f];
48 // finish with the remaining characters
54 if ( encLen
> dstLen
)
57 // we have definitely one and maybe two bytes remaining
58 unsigned char next
= srcLen
== 2 ? src
[1] : 0;
59 *dst
++ = b64
[src
[0] >> 2];
60 *dst
++ = b64
[((src
[0] & 0x03) << 4) | ((next
& 0xf0) >> 4)];
61 *dst
++ = srcLen
== 2 ? b64
[((next
& 0x0f) << 2)] : '=';
70 wxBase64Decode(void *dst_
, size_t dstLen
,
71 const char *src
, size_t srcLen
,
72 wxBase64DecodeMode mode
,
75 wxCHECK_MSG( src
, wxCONV_FAILED
, wxT("NULL input buffer") );
77 unsigned char *dst
= static_cast<unsigned char *>(dst_
);
81 if ( srcLen
== wxNO_LEN
)
84 // this table contains the values, in base 64, of all valid characters and
85 // special values WSP or INV for white space and invalid characters
86 // respectively as well as a special PAD value for '='
94 static const unsigned char decode
[256] =
96 WSP
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,WSP
,WSP
,INV
,WSP
,WSP
,INV
,INV
,
97 INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,
98 WSP
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,INV
,076,INV
,INV
,INV
,077,
99 064,065,066,067,070,071,072,073,074,075,INV
,INV
,INV
,PAD
,INV
,INV
,
100 INV
,000,001,002,003,004,005,006,007,010,011,012,013,014,015,016,
101 017,020,021,022,023,024,025,026,027,030,031,INV
,INV
,INV
,INV
,INV
,
102 INV
,032,033,034,035,036,037,040,041,042,043,044,045,046,047,050,
103 051,052,053,054,055,056,057,060,061,062,063,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
,
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
,
114 // we decode input by groups of 4 characters but things are complicated by
115 // the fact that there can be whitespace and other junk in it too so keep
116 // record of where exactly we're inside the current quartet in this var
118 unsigned char in
[4]; // current quartet
119 bool end
= false; // set when we find padding
120 size_t padLen
= 0; // length lost to padding
122 for ( p
= src
; srcLen
; p
++, srcLen
-- )
124 const unsigned char c
= decode
[static_cast<unsigned char>(*p
)];
128 if ( mode
== wxBase64DecodeMode_SkipWS
)
133 if ( mode
== wxBase64DecodeMode_Relaxed
)
136 // force the loop to stop and an error to be returned
142 // set the flag telling us that we're past the end now
145 // there can be either a single '=' at the end of a quartet or
146 // "==" in positions 2 and 3
152 else if ( (n
== 2) && (--srcLen
&& *++p
== '=') )
158 else // invalid padding
160 // force the loop terminate with an error
169 // nothing is allowed after the end so provoke error return
180 // got entire block, decode
181 decLen
+= 3 - padLen
;
184 if ( decLen
> dstLen
)
185 return wxCONV_FAILED
;
187 // undo the bit shifting done during encoding
188 *dst
++ = in
[0] << 2 | in
[1] >> 4;
190 // be careful to not overwrite the output buffer with NUL pad
194 *dst
++ = in
[1] << 4 | in
[2] >> 2;
196 *dst
++ = in
[2] << 6 | in
[3];
208 // notice that the error was on a previous position as we did one
209 // extra "p++" in the loop line after it
210 *posErr
= p
- src
- 1;
213 return wxCONV_FAILED
;
219 wxMemoryBuffer
wxBase64Decode(const char *src
,
221 wxBase64DecodeMode mode
,
225 wxCHECK_MSG( src
, buf
, wxT("NULL input buffer") );
227 if ( srcLen
== wxNO_LEN
)
228 srcLen
= strlen(src
);
230 size_t len
= wxBase64DecodedSize(srcLen
);
231 len
= wxBase64Decode(buf
.GetWriteBuf(len
), len
, src
, srcLen
, mode
, posErr
);
232 if ( len
== wxCONV_FAILED
)
240 #endif // wxUSE_BASE64