| 854 | const char encodeBase64Table[64 + 1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 855 | |
| 856 | DataBuf decodeBase64(const std::string& src) { |
| 857 | // create decoding table |
| 858 | unsigned long invalid = 64; |
| 859 | auto decodeBase64Table = std::vector<unsigned long>(256, invalid); |
| 860 | for (unsigned long i = 0; i < 64; i++) |
| 861 | decodeBase64Table[static_cast<unsigned char>(encodeBase64Table[i])] = i; |
| 862 | |
| 863 | // calculate dest size |
| 864 | auto validSrcSize = static_cast<unsigned long>( |
| 865 | std::count_if(src.begin(), src.end(), [&](unsigned char c) { return decodeBase64Table.at(c) != invalid; })); |
| 866 | if (validSrcSize > ULONG_MAX / 3) |
| 867 | return {}; // avoid integer overflow |
| 868 | const unsigned long destSize = (validSrcSize * 3) / 4; |
| 869 | |
| 870 | // allocate dest buffer |
| 871 | DataBuf dest(destSize); |
| 872 | |
| 873 | // decode |
| 874 | for (unsigned long srcPos = 0, destPos = 0; destPos < destSize;) { |
| 875 | unsigned long buffer = 0; |
| 876 | for (int bufferPos = 3; bufferPos >= 0 && srcPos < src.size(); srcPos++) { |
| 877 | unsigned long srcValue = decodeBase64Table[static_cast<unsigned char>(src[srcPos])]; |
| 878 | if (srcValue == invalid) |
| 879 | continue; |
| 880 | buffer |= srcValue << (bufferPos * 6); |
| 881 | bufferPos--; |
| 882 | } |
| 883 | for (int bufferPos = 2; bufferPos >= 0 && destPos < destSize; bufferPos--, destPos++) { |
| 884 | dest.write_uint8(destPos, static_cast<byte>((buffer >> (bufferPos * 8)) & 0xFF)); |
| 885 | } |
| 886 | } |
| 887 | return dest; |
| 888 | } |
| 889 | |
| 890 | DataBuf decodeAi7Thumbnail(const DataBuf& src) { |
| 891 | const byte* colorTable = src.c_data(); |
no test coverage detected