This repository has been archived on 2021-11-25. You can view files and clone it, but cannot push or open issues/pull-requests.
KChatWSServer/base64.hpp

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, '-', '_', '=');
}