added functions for base64 en/decoding (replaces patch 1739431)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@47282 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
226
src/common/base64.cpp
Normal file
226
src/common/base64.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/common/base64.cpp
|
||||
// Purpose: implementation of BASE64 encoding/decoding functions
|
||||
// Author: Charles Reimers, Vadim Zeitlin
|
||||
// Created: 2007-06-18
|
||||
// RCS-ID: $Id$
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#if wxUSE_BASE64
|
||||
|
||||
#include "wx/base64.h"
|
||||
|
||||
size_t
|
||||
wxBase64Encode(char *dst, size_t dstLen, const void *src_, size_t srcLen)
|
||||
{
|
||||
wxCHECK_MSG( src_, wxCONV_FAILED, _T("NULL input buffer") );
|
||||
|
||||
const unsigned char *src = wx_static_cast(const unsigned char *, src_);
|
||||
|
||||
static const char b64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
|
||||
size_t encLen = 0;
|
||||
|
||||
// encode blocks of 3 bytes into 4 base64 characters
|
||||
for ( ; srcLen >= 3; srcLen -= 3, src += 3 )
|
||||
{
|
||||
encLen += 4;
|
||||
if ( dst )
|
||||
{
|
||||
if ( encLen > dstLen )
|
||||
return wxCONV_FAILED;
|
||||
|
||||
*dst++ = b64[src[0] >> 2];
|
||||
*dst++ = b64[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)];
|
||||
*dst++ = b64[((src[1] & 0x0f) << 2) | ((src[2] & 0xc0) >> 6)];
|
||||
*dst++ = b64[src[2] & 0x3f];
|
||||
}
|
||||
}
|
||||
|
||||
// finish with the remaining characters
|
||||
if ( srcLen )
|
||||
{
|
||||
encLen += 4;
|
||||
if ( dst )
|
||||
{
|
||||
if ( encLen > dstLen )
|
||||
return wxCONV_FAILED;
|
||||
|
||||
// we have definitely one and maybe two bytes remaining
|
||||
unsigned char next = srcLen == 2 ? src[1] : 0;
|
||||
*dst++ = b64[src[0] >> 2];
|
||||
*dst++ = b64[((src[0] & 0x03) << 4) | ((next & 0xf0) >> 4)];
|
||||
*dst++ = srcLen == 2 ? b64[((next & 0x0f) << 2)] : '=';
|
||||
*dst = '=';
|
||||
}
|
||||
}
|
||||
|
||||
return encLen;
|
||||
}
|
||||
|
||||
size_t
|
||||
wxBase64Decode(void *dst_, size_t dstLen,
|
||||
const char *src, size_t srcLen,
|
||||
wxBase64DecodeMode mode,
|
||||
size_t *posErr)
|
||||
{
|
||||
wxCHECK_MSG( src, wxCONV_FAILED, _T("NULL input buffer") );
|
||||
|
||||
unsigned char *dst = wx_static_cast(unsigned char *, dst_);
|
||||
|
||||
size_t decLen = 0;
|
||||
|
||||
if ( srcLen == wxNO_LEN )
|
||||
srcLen = strlen(src);
|
||||
|
||||
// this table contains the values, in base 64, of all valid characters and
|
||||
// special values WSP or INV for white space and invalid characters
|
||||
// respectively as well as a special PAD value for '='
|
||||
enum
|
||||
{
|
||||
WSP = 200,
|
||||
INV,
|
||||
PAD
|
||||
};
|
||||
|
||||
static const char decode[256] =
|
||||
{
|
||||
WSP,INV,INV,INV,INV,INV,INV,INV,INV,WSP,WSP,INV,WSP,WSP,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
WSP,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,076,INV,INV,INV,077,
|
||||
064,065,066,067,070,071,072,073,074,075,INV,INV,INV,PAD,INV,INV,
|
||||
INV,000,001,002,003,004,005,006,007,010,011,012,013,014,015,016,
|
||||
017,020,021,022,023,024,025,026,027,030,031,INV,INV,INV,INV,INV,
|
||||
INV,032,033,034,035,036,037,040,041,042,043,044,045,046,047,050,
|
||||
051,052,053,054,055,056,057,060,061,062,063,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
|
||||
};
|
||||
|
||||
// we decode input by groups of 4 characters but things are complicated by
|
||||
// the fact that there can be whitespace and other junk in it too so keep
|
||||
// record of where exactly we're inside the current quartet in this var
|
||||
int n = 0;
|
||||
unsigned char in[4]; // current quartet
|
||||
bool end = false; // set when we find padding
|
||||
size_t padLen = 0; // length lost to padding
|
||||
const char *p;
|
||||
for ( p = src; srcLen; p++, srcLen-- )
|
||||
{
|
||||
const char c = decode[(int)*p]; // cast just to suppress warnings
|
||||
switch ( c )
|
||||
{
|
||||
case WSP:
|
||||
if ( mode == wxBase64DecodeMode_SkipWS )
|
||||
continue;
|
||||
// fall through
|
||||
|
||||
case INV:
|
||||
if ( mode == wxBase64DecodeMode_Relaxed )
|
||||
continue;
|
||||
|
||||
// force the loop to stop and an error to be returned
|
||||
n = -1;
|
||||
srcLen = 0;
|
||||
break;
|
||||
|
||||
case PAD:
|
||||
// set the flag telling us that we're past the end now
|
||||
end = true;
|
||||
|
||||
// there can be either a single '=' at the end of a quartet or
|
||||
// "==" in positions 2 and 3
|
||||
if ( n == 3 )
|
||||
{
|
||||
padLen = 1;
|
||||
in[n++] = '\0';
|
||||
}
|
||||
else if ( (n == 2) && (--srcLen && *++p == '=') )
|
||||
{
|
||||
padLen = 2;
|
||||
in[n++] = '\0';
|
||||
in[n++] = '\0';
|
||||
}
|
||||
else // invalid padding
|
||||
{
|
||||
// force the loop terminate with an error
|
||||
n = -1;
|
||||
srcLen = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( end )
|
||||
{
|
||||
// nothing is allowed after the end so provoke error return
|
||||
n = -1;
|
||||
srcLen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
in[n++] = c;
|
||||
}
|
||||
|
||||
if ( n == 4 )
|
||||
{
|
||||
// got entire block, decode
|
||||
decLen += 3 - padLen;
|
||||
if ( dst )
|
||||
{
|
||||
if ( decLen > dstLen )
|
||||
return wxCONV_FAILED;
|
||||
|
||||
// undo the bit shifting done during encoding
|
||||
*dst++ = in[0] << 2 | in[1] >> 4;
|
||||
*dst++ = in[1] << 4 | in[2] >> 2;
|
||||
*dst++ = in[2] << 6 | in[3];
|
||||
}
|
||||
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( n )
|
||||
{
|
||||
if ( posErr )
|
||||
*posErr = p - src;
|
||||
|
||||
return wxCONV_FAILED;
|
||||
}
|
||||
|
||||
return decLen;
|
||||
}
|
||||
|
||||
wxMemoryBuffer wxBase64Decode(const char *src,
|
||||
size_t srcLen,
|
||||
wxBase64DecodeMode mode,
|
||||
size_t *posErr)
|
||||
{
|
||||
wxMemoryBuffer buf;
|
||||
wxCHECK_MSG( src, buf, _T("NULL input buffer") );
|
||||
|
||||
if ( srcLen == wxNO_LEN )
|
||||
srcLen = strlen(src);
|
||||
|
||||
size_t len = wxBase64DecodedSize(srcLen);
|
||||
len = wxBase64Decode(buf.GetWriteBuf(len), len, src, srcLen, mode, posErr);
|
||||
if ( len == wxCONV_FAILED )
|
||||
len = 0;
|
||||
|
||||
buf.SetDataLen(len);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif // wxUSE_BASE64
|
||||
Reference in New Issue
Block a user