164 lines
4.1 KiB
C++
164 lines
4.1 KiB
C++
#include <string>
|
|
#include <vector>
|
|
|
|
// base64 encode list
|
|
// 0-25 A-Z
|
|
// 26-51 a-z
|
|
// 52-61 0-9
|
|
inline char _base64_encode_char(unsigned int c, char c62, char c63)
|
|
{
|
|
static const char* _base64_encode_list =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
"0123456789";
|
|
if (c < 62) return _base64_encode_list[c];
|
|
else if (c == 62) return c62;
|
|
else return c63;
|
|
}
|
|
|
|
// base64 decode list
|
|
// A-Z 0-25
|
|
// a-z 26-51
|
|
// 0-9 52-61
|
|
inline unsigned int _base64_decode_char(char c, char c62, char c63)
|
|
{
|
|
if (c >= 'A'&&c <= 'Z') return c - 'A';
|
|
else if (c >= 'a'&&c <= 'z') return c - 'a' + 26;
|
|
else if (c >= '0'&&c <= '9') return c - '0' + 52;
|
|
else if (c == c62) return 62;
|
|
else return 63;
|
|
}
|
|
|
|
std::string base64_encode(const unsigned char* data, int len, char c62, char c63, char cfill)
|
|
{
|
|
std::string ans;
|
|
int nGroup = len / 3;
|
|
int nLeft = len % 3;
|
|
|
|
for (int i = 0; i < nGroup; i++)
|
|
{
|
|
unsigned int xa = data[i * 3];
|
|
unsigned int xb = data[i * 3 + 1];
|
|
unsigned int xc = data[i * 3 + 2];
|
|
|
|
unsigned int ya = (xa & 0xfc) >> 2; // 11111100,...
|
|
unsigned int yb = ((xa & 0x3) << 4) | ((xb & 0xf0) >> 4); // 00000011,11110000,....
|
|
unsigned int yc = ((xb & 0xf) << 2) | ((xc & 0xc0) >> 6); // ...,00001111,11000000
|
|
unsigned int yd = xc & 0x3f; // ...,00111111
|
|
|
|
ans.push_back(_base64_encode_char(ya, c62, c63));
|
|
ans.push_back(_base64_encode_char(yb, c62, c63));
|
|
ans.push_back(_base64_encode_char(yc, c62, c63));
|
|
ans.push_back(_base64_encode_char(yd, c62, c63));
|
|
}
|
|
|
|
switch (nLeft)
|
|
{
|
|
case 1:
|
|
{
|
|
unsigned int xa = data[nGroup * 3];
|
|
|
|
unsigned int ya = (xa & 0xfc) >> 2;
|
|
unsigned int yb = (xa & 0x3) << 4;
|
|
|
|
ans.push_back(_base64_encode_char(ya, c62, c63));
|
|
ans.push_back(_base64_encode_char(yb, c62, c63));
|
|
ans.push_back(cfill);
|
|
ans.push_back(cfill);
|
|
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
unsigned int xa = data[nGroup * 3];
|
|
unsigned int xb = data[nGroup * 3 + 1];
|
|
|
|
unsigned int ya = (xa & 0xfc) >> 2;
|
|
unsigned int yb = ((xa & 0x3) << 4) | ((xb & 0xf0) >> 4);
|
|
unsigned int yc = (xb & 0xf) << 2;
|
|
|
|
ans.push_back(_base64_encode_char(ya, c62, c63));
|
|
ans.push_back(_base64_encode_char(yb, c62, c63));
|
|
ans.push_back(_base64_encode_char(yc, c62, c63));
|
|
ans.push_back(cfill);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ans;
|
|
}
|
|
|
|
std::vector<unsigned char> base64_decode(const std::string& str, char c62, char c63, char cfill)
|
|
{
|
|
std::vector<unsigned char> data;
|
|
int nGroup = str.size() / 4;
|
|
for (int i = 0; i < nGroup; i++)
|
|
{
|
|
unsigned int ya = _base64_decode_char(str[i * 4], c62, c63);
|
|
unsigned int yb = _base64_decode_char(str[i * 4 + 1], c62, c63);
|
|
unsigned int xa = (ya << 2) | (yb >> 4); // 6 + 2
|
|
data.push_back(xa);
|
|
|
|
if (str[i * 4 + 3] != cfill)
|
|
{
|
|
unsigned int yc = _base64_decode_char(str[i * 4 + 2], c62, c63);
|
|
unsigned int yd = _base64_decode_char(str[i * 4 + 3], c62, c63);
|
|
|
|
unsigned int xb = ((yb & 0xf) << 4) | (yc >> 2); // 4 + 4
|
|
unsigned int xc = ((yc & 0x3) << 6) | yd; // 2 + 6
|
|
|
|
data.push_back(xb);
|
|
data.push_back(xc);
|
|
}
|
|
else // (str[i * 4 + 3] == cfill)
|
|
{
|
|
if (str[i * 4 + 2] == cfill)
|
|
{
|
|
unsigned int xb = (yb & 0xf) << 4; // 4 + 4
|
|
|
|
data.push_back(xb);
|
|
}
|
|
else
|
|
{
|
|
unsigned int yc = _base64_decode_char(str[i * 4 + 2], c62, c63);
|
|
unsigned int xb = ((yb & 0xf) << 4) | (yc >> 2); // 4 + 4
|
|
unsigned int xc = (yc & 0x3) << 6; // 2 + 6
|
|
|
|
data.push_back(xb);
|
|
data.push_back(xc);
|
|
}
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
std::string base64_encode_std(const unsigned char* data, int len)
|
|
{
|
|
return base64_encode(data, len, '+', '/', '=');
|
|
}
|
|
|
|
std::string base64_encode_std(const std::string& data)
|
|
{
|
|
return base64_encode_std((const unsigned char*)data.data(), data.size());
|
|
}
|
|
|
|
std::string base64_encode_url(const unsigned char* data, int len)
|
|
{
|
|
return base64_encode(data, len, '-', '_', '=');
|
|
}
|
|
|
|
std::string base64_encode_url(const std::string& data)
|
|
{
|
|
return base64_encode_std((const unsigned char*)data.data(), data.size());
|
|
}
|
|
|
|
std::vector<unsigned char> base64_decode_std(const std::string& str)
|
|
{
|
|
return base64_decode(str, '+', '/', '=');
|
|
}
|
|
|
|
std::vector<unsigned char> base64_decode_url(const std::string& str)
|
|
{
|
|
return base64_decode(str, '-', '_', '=');
|
|
} |