#include "base64.h" namespace { int DecodeCharacter(const unsigned char character) { if (character >= 'A' && character <= 'Z') return character - 'A'; if (character >= 'a' && character <= 'z') return character - 'a' + 26; if (character >= '0' && character <= '9') return character - '0' + 52; if (character == '+') return 62; if (character == '/') return 63; return -1; } } // namespace void idBase64::Encode(const unsigned char* source, const int size) { static const unsigned char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; if (source == nullptr || size <= 0) { if (EnsureAlloced(1)) data[0] = 0; len = 0; return; } const int outputLength = ((size + 2) / 3) * 4; if (!EnsureAlloced(outputLength + 1)) return; len = 0; int input = 0; while (input + 2 < size) { const unsigned int value = (static_cast(source[input]) << 16) | (static_cast(source[input + 1]) << 8) | source[input + 2]; data[len++] = alphabet[(value >> 18) & 63]; data[len++] = alphabet[(value >> 12) & 63]; data[len++] = alphabet[(value >> 6) & 63]; data[len++] = alphabet[value & 63]; input += 3; } if (size - input == 1) { const unsigned int value = static_cast(source[input]) << 16; data[len++] = alphabet[(value >> 18) & 63]; data[len++] = alphabet[(value >> 12) & 63]; data[len++] = '='; data[len++] = '='; } else if (size - input == 2) { const unsigned int value = (static_cast(source[input]) << 16) | (static_cast(source[input + 1]) << 8); data[len++] = alphabet[(value >> 18) & 63]; data[len++] = alphabet[(value >> 12) & 63]; data[len++] = alphabet[(value >> 6) & 63]; data[len++] = '='; } data[len] = 0; } int idBase64::Decode(unsigned char* destination) const { if (destination == nullptr || data == nullptr || len == 0 || (len & 3) != 0) return 0; int output = 0; for (int input = 0; input < len; input += 4) { const bool lastGroup = input + 4 == len; const bool pad2 = data[input + 2] == '='; const bool pad3 = data[input + 3] == '='; if ((!lastGroup && (pad2 || pad3)) || (pad2 && !pad3)) return 0; const int a = DecodeCharacter(data[input]); const int b = DecodeCharacter(data[input + 1]); const int c = pad2 ? 0 : DecodeCharacter(data[input + 2]); const int d = pad3 ? 0 : DecodeCharacter(data[input + 3]); if (a < 0 || b < 0 || c < 0 || d < 0) return 0; const unsigned int value = (static_cast(a) << 18) | (static_cast(b) << 12) | (static_cast(c) << 6) | static_cast(d); destination[output++] = static_cast(value >> 16); if (!pad2) destination[output++] = static_cast(value >> 8); if (!pad3) destination[output++] = static_cast(value); } destination[output] = 0; return output; }