1e509ee18Sopenharmony_ci/* 2e509ee18Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3e509ee18Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e509ee18Sopenharmony_ci * you may not use this file except in compliance with the License. 5e509ee18Sopenharmony_ci * You may obtain a copy of the License at 6e509ee18Sopenharmony_ci * 7e509ee18Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e509ee18Sopenharmony_ci * 9e509ee18Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e509ee18Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e509ee18Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e509ee18Sopenharmony_ci * See the License for the specific language governing permissions and 13e509ee18Sopenharmony_ci * limitations under the License. 14e509ee18Sopenharmony_ci */ 15e509ee18Sopenharmony_ci 16e509ee18Sopenharmony_ci#include "tooling/base/pt_base64.h" 17e509ee18Sopenharmony_ci 18e509ee18Sopenharmony_cinamespace panda::ecmascript::tooling { 19e509ee18Sopenharmony_cistatic const unsigned char DECODE_TABLE[] = { 20e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 21e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 23e509ee18Sopenharmony_ci 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255, 24e509ee18Sopenharmony_ci 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 25e509ee18Sopenharmony_ci 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 26e509ee18Sopenharmony_ci 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 27e509ee18Sopenharmony_ci 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 28e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 29e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 30e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 32e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 33e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 34e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 35e509ee18Sopenharmony_ci 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 36e509ee18Sopenharmony_ci}; 37e509ee18Sopenharmony_ci 38e509ee18Sopenharmony_cistatic const char ENCODE_TABLE[] = { 39e509ee18Sopenharmony_ci "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 40e509ee18Sopenharmony_ci "abcdefghijklmnopqrstuvwxyz" 41e509ee18Sopenharmony_ci "0123456789+/" 42e509ee18Sopenharmony_ci}; 43e509ee18Sopenharmony_ci 44e509ee18Sopenharmony_cistd::pair<std::size_t, bool> PtBase64::Decode(void *output, const char *input, std::size_t len) 45e509ee18Sopenharmony_ci{ 46e509ee18Sopenharmony_ci if (len < ENCODED_GROUP_BYTES || len % ENCODED_GROUP_BYTES != 0) { 47e509ee18Sopenharmony_ci return {0, false}; 48e509ee18Sopenharmony_ci } 49e509ee18Sopenharmony_ci 50e509ee18Sopenharmony_ci auto *src = reinterpret_cast<unsigned char const *>(input); 51e509ee18Sopenharmony_ci char *dest = static_cast<char *>(output); 52e509ee18Sopenharmony_ci char base64Chars[ENCODED_GROUP_BYTES]; 53e509ee18Sopenharmony_ci int8_t i = 0; 54e509ee18Sopenharmony_ci while (len-- && *src != '=') { 55e509ee18Sopenharmony_ci auto v = DECODE_TABLE[*src]; 56e509ee18Sopenharmony_ci if (v == INVAILD_VALUE) { 57e509ee18Sopenharmony_ci break; 58e509ee18Sopenharmony_ci } 59e509ee18Sopenharmony_ci base64Chars[i++] = v; 60e509ee18Sopenharmony_ci 61e509ee18Sopenharmony_ci if (i == ENCODED_GROUP_BYTES) { 62e509ee18Sopenharmony_ci *dest++ = (base64Chars[0] << 2) | ((base64Chars[1] & 0x30) >> 4); // 2: shift 2bits, 4: shift 4bits 63e509ee18Sopenharmony_ci *dest++ = (base64Chars[1] << 4) | ((base64Chars[2] & 0x3c) >> 2); // 2: shift 2bits, 4: shift 4bits 64e509ee18Sopenharmony_ci *dest++ = (base64Chars[2] << 6) | base64Chars[3]; // 6: shift 6bits, 2: the second char, 3: the third char 65e509ee18Sopenharmony_ci i = 0; 66e509ee18Sopenharmony_ci } 67e509ee18Sopenharmony_ci src++; 68e509ee18Sopenharmony_ci } 69e509ee18Sopenharmony_ci 70e509ee18Sopenharmony_ci if (i != 0) { 71e509ee18Sopenharmony_ci char tmp[UNENCODED_GROUP_BYTES]; 72e509ee18Sopenharmony_ci tmp[0] = (base64Chars[0] << 2) | ((base64Chars[1] & 0x30) >> 4); // 2: shift 2bits, 4: shift 4bits 73e509ee18Sopenharmony_ci tmp[1] = (base64Chars[1] << 4) | ((base64Chars[2] & 0x3c) >> 2); // 2: shift 2bits, 4: shift 4bits 74e509ee18Sopenharmony_ci tmp[2] = (base64Chars[2] << 6) | base64Chars[3]; // 6: shift 6bits, 2: the second char, 3: the third char 75e509ee18Sopenharmony_ci for (int8_t j = 0; j < i - 1; j++) { 76e509ee18Sopenharmony_ci *dest++ = tmp[j]; 77e509ee18Sopenharmony_ci } 78e509ee18Sopenharmony_ci } 79e509ee18Sopenharmony_ci 80e509ee18Sopenharmony_ci len++; // get the remaining length and also avoid underflow 81e509ee18Sopenharmony_ci size_t decodedLen = dest - static_cast<char *>(output); 82e509ee18Sopenharmony_ci bool decodedDone = false; 83e509ee18Sopenharmony_ci // 0: decodedDone, 1: =, 2: == 84e509ee18Sopenharmony_ci if (len == 0 || (len == 1 && *src == '=') || (len == 2 && *src == '=' && *(src + 1) == '=')) { 85e509ee18Sopenharmony_ci decodedDone = true; 86e509ee18Sopenharmony_ci } 87e509ee18Sopenharmony_ci 88e509ee18Sopenharmony_ci return {decodedLen, decodedDone}; 89e509ee18Sopenharmony_ci} 90e509ee18Sopenharmony_ci 91e509ee18Sopenharmony_cisize_t PtBase64::Encode(char *output, const void *input, std::size_t len) 92e509ee18Sopenharmony_ci{ 93e509ee18Sopenharmony_ci if (len == 0) { 94e509ee18Sopenharmony_ci return 0; 95e509ee18Sopenharmony_ci } 96e509ee18Sopenharmony_ci 97e509ee18Sopenharmony_ci auto *src = static_cast<const unsigned char *>(input); 98e509ee18Sopenharmony_ci char *dest = output; 99e509ee18Sopenharmony_ci for (auto n = len / UNENCODED_GROUP_BYTES; n--;) { 100e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[src[0] >> 2]; // 2: shift 2bits 101e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[((src[0] & 0x03) << 4) | (src[1] >> 4)]; // 4: shift 4bits 102e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[((src[1] & 0x0f) << 2) | (src[2] >> 6)]; // 2: shift 2bits, 6: shift 6bits 103e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[src[2] & 0x3f]; // 2: the second char 104e509ee18Sopenharmony_ci 105e509ee18Sopenharmony_ci src += UNENCODED_GROUP_BYTES; 106e509ee18Sopenharmony_ci } 107e509ee18Sopenharmony_ci 108e509ee18Sopenharmony_ci int8_t remainder = static_cast<int8_t>(len % UNENCODED_GROUP_BYTES); 109e509ee18Sopenharmony_ci int8_t paddingCnt = (UNENCODED_GROUP_BYTES - remainder) % UNENCODED_GROUP_BYTES; 110e509ee18Sopenharmony_ci switch (paddingCnt) { 111e509ee18Sopenharmony_ci case 1: 112e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[src[0] >> 2]; // 2: shift 2bits 113e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[((src[0] & 0x03) << 4) | (src[1] >> 4)]; // 4: shift 4bits 114e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[((src[1] & 0x0f) << 2)]; // 2: shift 2bits 115e509ee18Sopenharmony_ci *dest++ = '='; 116e509ee18Sopenharmony_ci break; 117e509ee18Sopenharmony_ci case 2: // 2: "==" 118e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[src[0] >> 2]; // 2: shift 2bits 119e509ee18Sopenharmony_ci *dest++ = ENCODE_TABLE[((src[0] & 0x03) << 4)]; // 4: shift 4bits 120e509ee18Sopenharmony_ci *dest++ = '='; 121e509ee18Sopenharmony_ci *dest++ = '='; 122e509ee18Sopenharmony_ci break; 123e509ee18Sopenharmony_ci default: 124e509ee18Sopenharmony_ci break; 125e509ee18Sopenharmony_ci } 126e509ee18Sopenharmony_ci return dest - output; 127e509ee18Sopenharmony_ci} 128e509ee18Sopenharmony_ci} // namespace panda::ecmascript::tooling