#include #include // 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 base64_decode(const std::string& str, char c62, char c63, char cfill) { std::vector 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 base64_decode_std(const std::string& str) { return base64_decode(str, '+', '/', '='); } std::vector base64_decode_url(const std::string& str) { return base64_decode(str, '-', '_', '='); }