// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. // // simple base64 decoder #include "base64decode.h" #include #include #include namespace base64 { using namespace std; string Base64::Decode(const string &encoded) { string s = encoded; while (s.size() % 4 != 0) { s.append("="); } size_t n = s.size(); size_t padding = 0; if (n >= 1 && s[n - 1] == '=') { padding = 1; if (n >= 2 && s[n - 2] == '=') { padding = 2; if (n >= 3 && s[n - 3] == '=') { padding = 3; } } } // We divide first to avoid overflow. It's OK to do this because we // already made sure that n % 4 == 0. size_t outLen = (n / 4) * 3 - padding; std::unique_ptr buffer(new uint8_t[outLen]); if (!buffer) { return ""; } uint8_t *out = buffer.get(); size_t j = 0; uint32_t accum = 0; for (size_t i = 0; i < n; ++i) { char c = s[i]; unsigned value; if (c >= 'A' && c <= 'Z') { value = c - 'A'; } else if (c >= 'a' && c <= 'z') { value = 26 + c - 'a'; } else if (c >= '0' && c <= '9') { value = 52 + c - '0'; } else if (c == '+' || c == '-') { value = 62; } else if (c == '/' || c == '_') { value = 63; } else { if (c != '=') { std::cerr << "unexpected character in base64 decode:" << c << std::endl; } value = 0; } accum = (accum << 6) | value; if (((i + 1) % 4) == 0) { if (j < outLen) { out[j++] = (accum >> 16); } if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } if (j < outLen) { out[j++] = accum & 0xff; } accum = 0; } } return string((char *)buffer.get(), outLen); } } // namespace base64