13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "base64.h" 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_cinamespace panda::es2panda::util { 193af6ab5fSopenharmony_cistd::string Base64Encode(const std::string &inputString) 203af6ab5fSopenharmony_ci{ 213af6ab5fSopenharmony_ci size_t strLen = inputString.length(); 223af6ab5fSopenharmony_ci size_t encodedStrLen = strLen / TO_TRANSFORM_CHAR_NUM * TRANSFORMED_CHAR_NUM; 233af6ab5fSopenharmony_ci if (strLen % TO_TRANSFORM_CHAR_NUM != 0) { 243af6ab5fSopenharmony_ci encodedStrLen += TRANSFORMED_CHAR_NUM; 253af6ab5fSopenharmony_ci } 263af6ab5fSopenharmony_ci std::string encodedRes = std::string(encodedStrLen, '\0'); 273af6ab5fSopenharmony_ci const char* base64CharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 283af6ab5fSopenharmony_ci // 2: the index do not exceed the range of encodedRes and form a complete four-character block 293af6ab5fSopenharmony_ci for (size_t i = 0, j = 0; i < encodedRes.length() - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { 303af6ab5fSopenharmony_ci // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit 313af6ab5fSopenharmony_ci // former 00 + first 6 bits of the first char 323af6ab5fSopenharmony_ci encodedRes[i] = base64CharSet[(static_cast<unsigned int>(inputString[j]) & 0xff) >> 2]; 333af6ab5fSopenharmony_ci // 00 + the last 2 bits of the first char + the first 4 bits of the second char 343af6ab5fSopenharmony_ci encodedRes[i + 1] = base64CharSet[(static_cast<unsigned int>(inputString[j]) & 0x03) << 4 | 353af6ab5fSopenharmony_ci (static_cast<unsigned int>(inputString[j + 1]) & 0xf0) >> 4]; 363af6ab5fSopenharmony_ci // 00 + last 4 bits of the second char + the first 2 bits of the third char 373af6ab5fSopenharmony_ci encodedRes[i + 2] = base64CharSet[(static_cast<unsigned int>(inputString[j + 1]) & 0x0f) << 2 | 383af6ab5fSopenharmony_ci (static_cast<unsigned int>(inputString[j + 2]) & 0xc0) >> 6]; 393af6ab5fSopenharmony_ci // 00 + the last 6 bits of the third char 403af6ab5fSopenharmony_ci encodedRes[i + 3] = base64CharSet[static_cast<unsigned int>(inputString[j + 2]) & 0x3f]; 413af6ab5fSopenharmony_ci } 423af6ab5fSopenharmony_ci switch (strLen % TO_TRANSFORM_CHAR_NUM) { 433af6ab5fSopenharmony_ci // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes 443af6ab5fSopenharmony_ci case 1: 453af6ab5fSopenharmony_ci // 1,2: the original character is one, and two characters are missing after conversion 463af6ab5fSopenharmony_ci encodedRes[encodedRes.length() - 2] = '='; 473af6ab5fSopenharmony_ci encodedRes[encodedRes.length() - 1] = '='; 483af6ab5fSopenharmony_ci break; 493af6ab5fSopenharmony_ci case 2: 503af6ab5fSopenharmony_ci // 1: the original character is two, and a character are missing after conversion 513af6ab5fSopenharmony_ci encodedRes[encodedRes.length() - 1] = '='; 523af6ab5fSopenharmony_ci break; 533af6ab5fSopenharmony_ci default: 543af6ab5fSopenharmony_ci break; 553af6ab5fSopenharmony_ci } 563af6ab5fSopenharmony_ci return encodedRes; 573af6ab5fSopenharmony_ci} 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_cistd::string Base64Decode(const std::string &base64String) 603af6ab5fSopenharmony_ci{ 613af6ab5fSopenharmony_ci const int decodeTable[] = { 623af6ab5fSopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 633af6ab5fSopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 643af6ab5fSopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 653af6ab5fSopenharmony_ci -1, -1, -1, -1, -1, -1, -1, 663af6ab5fSopenharmony_ci 62, // '+' 673af6ab5fSopenharmony_ci -1, -1, -1, 683af6ab5fSopenharmony_ci 63, // '/' 693af6ab5fSopenharmony_ci 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'~'9' 703af6ab5fSopenharmony_ci -1, -1, -1, -1, -1, -1, -1, 713af6ab5fSopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 723af6ab5fSopenharmony_ci 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'~'Z' 733af6ab5fSopenharmony_ci -1, -1, -1, -1, -1, -1, 743af6ab5fSopenharmony_ci 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 753af6ab5fSopenharmony_ci 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 'a'~'z' 763af6ab5fSopenharmony_ci }; 773af6ab5fSopenharmony_ci 783af6ab5fSopenharmony_ci size_t strLen = base64String.length(); 793af6ab5fSopenharmony_ci size_t decodedStrLen = strLen / TRANSFORMED_CHAR_NUM * TO_TRANSFORM_CHAR_NUM; 803af6ab5fSopenharmony_ci if (base64String.find("==") != std::string::npos) { 813af6ab5fSopenharmony_ci decodedStrLen -= std::string("==").length(); 823af6ab5fSopenharmony_ci } else if (base64String.find("=") != std::string::npos) { 833af6ab5fSopenharmony_ci decodedStrLen -= std::string("=").length(); 843af6ab5fSopenharmony_ci } 853af6ab5fSopenharmony_ci std::string decodedRes = std::string(decodedStrLen, '\0'); 863af6ab5fSopenharmony_ci int firstChar = 0; 873af6ab5fSopenharmony_ci int secondChar = 0; 883af6ab5fSopenharmony_ci int thirdChar = 0; 893af6ab5fSopenharmony_ci int fourthChar = 0; 903af6ab5fSopenharmony_ci // 2: the index do not exceed the range of encodedRes and form a complete four-character block 913af6ab5fSopenharmony_ci for (size_t i = 0, j = 0; i < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { 923af6ab5fSopenharmony_ci // 1,2,3 is the nth character after the current position 933af6ab5fSopenharmony_ci firstChar = decodeTable[static_cast<unsigned char>(base64String[i])]; 943af6ab5fSopenharmony_ci secondChar = decodeTable[static_cast<unsigned char>(base64String[i + 1])]; 953af6ab5fSopenharmony_ci thirdChar = decodeTable[static_cast<unsigned char>(base64String[i + 2])]; 963af6ab5fSopenharmony_ci fourthChar = decodeTable[static_cast<unsigned char>(base64String[i + 3])]; 973af6ab5fSopenharmony_ci 983af6ab5fSopenharmony_ci if (firstChar == -1 || secondChar == -1) { 993af6ab5fSopenharmony_ci return ""; 1003af6ab5fSopenharmony_ci } 1013af6ab5fSopenharmony_ci // the last 6 bit of the first char + the 2~3 bit of the second char(first 4 bit - 00) 1023af6ab5fSopenharmony_ci decodedRes[j] = (static_cast<unsigned int>(firstChar) << 2) | (static_cast<unsigned int>(secondChar) >> 4); 1033af6ab5fSopenharmony_ci if (j == decodedStrLen - 1) { 1043af6ab5fSopenharmony_ci break; 1053af6ab5fSopenharmony_ci } 1063af6ab5fSopenharmony_ci if (thirdChar == -1) { 1073af6ab5fSopenharmony_ci return ""; 1083af6ab5fSopenharmony_ci } 1093af6ab5fSopenharmony_ci // the last 4 bit of the second char + the 2~5 bit of the third char(first 6 bit - 00) 1103af6ab5fSopenharmony_ci decodedRes[j + 1] = (static_cast<unsigned int>(secondChar) << 4) | (static_cast<unsigned int>(thirdChar) >> 2); 1113af6ab5fSopenharmony_ci if (j + 1 == decodedStrLen - 1) { 1123af6ab5fSopenharmony_ci break; 1133af6ab5fSopenharmony_ci } 1143af6ab5fSopenharmony_ci if (fourthChar == -1) { 1153af6ab5fSopenharmony_ci return ""; 1163af6ab5fSopenharmony_ci } 1173af6ab5fSopenharmony_ci // the last 2 bit of the third char + the last 6 bit of the fourth char 1183af6ab5fSopenharmony_ci decodedRes[j + 2] = (static_cast<unsigned int>(thirdChar) << 6) | static_cast<unsigned int>(fourthChar); 1193af6ab5fSopenharmony_ci } 1203af6ab5fSopenharmony_ci return decodedRes; 1213af6ab5fSopenharmony_ci} 1223af6ab5fSopenharmony_ci} // namespace panda::es2panda::util 123