1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "js_base64.h" 17 #include <cstring> 18 #include <sys/types.h> 19 #include "securec.h" 20 #include "napi/native_api.h" 21 #include "napi/native_node_api.h" 22 #include "tools/log.h" 23 24 namespace OHOS::Util { 25 namespace { 26 static const size_t TRAGET_TWO = 2; 27 static const size_t TRAGET_THREE = 3; 28 static const size_t TRAGET_FOUR = 4; 29 static const size_t TRAGET_SIX = 6; 30 static const size_t TRAGET_EIGHT = 8; 31 static const size_t TRAGET_SIXTYFIVE = 65; 32 const char BASE[] = { 33 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 34 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 35 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 36 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 61 37 }; 38 39 const char BASEURL[] = { 40 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 41 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 42 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 43 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95 44 }; 45 } 46 47 /* base64 encode */ EncodeSync(napi_env env,napi_value src,Type valueType)48 napi_value Base64::EncodeSync(napi_env env, napi_value src, Type valueType) 49 { 50 napi_typedarray_type type; 51 size_t length = 0; 52 void *resultData = nullptr; 53 napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr); 54 if (type != napi_uint8_array || length == 0) { 55 napi_throw_error(env, "401", 56 "Parameter error. The type of Parameter must be Uint8Array and the length greater than zero."); 57 return nullptr; 58 } 59 inputEncode_ = static_cast<const unsigned char*>(resultData); 60 unsigned char *rets = EncodeAchieve(inputEncode_, length, valueType); 61 if (rets == nullptr) { 62 napi_throw_error(env, "-1", "encode input is null"); 63 return nullptr; 64 } 65 void *data = nullptr; 66 napi_value arrayBuffer = nullptr; 67 size_t bufferSize = outputLen; 68 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 69 if (memcpy_s(data, bufferSize, reinterpret_cast<const void*>(rets), bufferSize) != EOK) { 70 FreeMemory(rets); 71 HILOG_ERROR("copy ret to arraybuffer error"); 72 return nullptr; 73 } 74 napi_value result = nullptr; 75 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 76 FreeMemory(rets); 77 return result; 78 } 79 80 /* base64 encodeToString */ EncodeToStringSync(napi_env env,napi_value src,Type valueType)81 napi_value Base64::EncodeToStringSync(napi_env env, napi_value src, Type valueType) 82 { 83 napi_typedarray_type type; 84 size_t length = 0; 85 void *resultData = nullptr; 86 napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr); 87 if (type != napi_uint8_array || length == 0) { 88 napi_throw_error(env, "401", 89 "Parameter error. The type of Parameter must be Uint8Array and the length greater than zero."); 90 return nullptr; 91 } 92 inputEncode_ = static_cast<const unsigned char*>(resultData); 93 unsigned char *ret = EncodeAchieve(inputEncode_, length, valueType); 94 if (ret == nullptr) { 95 FreeMemory(ret); 96 napi_throw_error(env, "-1", "encodeToString input is null"); 97 return nullptr; 98 } 99 const char *encString = reinterpret_cast<const char*>(ret); 100 napi_value resultStr = nullptr; 101 napi_create_string_utf8(env, encString, strlen(encString), &resultStr); 102 FreeMemory(ret); 103 return resultStr; 104 } 105 EncodeAchieve(const unsigned char * input,size_t inputLen,Type valueType)106 unsigned char *Base64::EncodeAchieve(const unsigned char *input, size_t inputLen, Type valueType) 107 { 108 unsigned char *ret = nullptr; 109 outputLen = (inputLen / TRAGET_THREE) * TRAGET_FOUR; 110 if ((inputLen % TRAGET_THREE) > 0) { 111 outputLen += TRAGET_FOUR; 112 } 113 if (outputLen > 0) { 114 ret = new (std::nothrow) unsigned char[outputLen + 1]; 115 if (ret == nullptr) { 116 HILOG_ERROR("Base64:: ret is nullptr"); 117 return nullptr; 118 } 119 if (memset_s(ret, outputLen + 1, '\0', outputLen + 1) != EOK) { 120 HILOG_ERROR("encode ret memset_s failed"); 121 FreeMemory(ret); 122 return nullptr; 123 } 124 } else { 125 HILOG_ERROR("outputLen is error"); 126 return nullptr; 127 } 128 if (ret == nullptr) { 129 return ret; 130 } 131 132 bool flag = false; 133 if (valueType == Type::BASIC_URL_SAFE || valueType == Type::MIME_URL_SAFE) { 134 flag = true; 135 } 136 const char *searchArray = flag ? BASEURL : BASE; 137 unsigned char *result = EncodeAchieveInner(input, ret, searchArray, inputLen, valueType); 138 return result; 139 } 140 EncodeAchieveInner(const unsigned char * input,unsigned char * ret,const char * searchArray,size_t inputLen,Type valueType)141 unsigned char *Base64::EncodeAchieveInner(const unsigned char *input, unsigned char *ret, 142 const char *searchArray, size_t inputLen, Type valueType) 143 { 144 size_t inp = 0; 145 size_t temp = 0; 146 size_t bitWise = 0; 147 size_t index = 0; 148 while (inp < inputLen) { 149 temp = 0; 150 bitWise = 0; 151 while (temp < TRAGET_THREE) { 152 if (inp >= inputLen) { 153 break; 154 } 155 bitWise = ((bitWise << TRAGET_EIGHT) | (input[inp] & XFF_FLG)); 156 inp++; 157 temp++; 158 } 159 bitWise = (bitWise << ((TRAGET_THREE - temp) * TRAGET_EIGHT)); 160 for (size_t i = 0; i < TRAGET_FOUR; i++) { 161 if (temp < i && (valueType == Type::BASIC_URL_SAFE || valueType == Type::MIME_URL_SAFE)) { 162 outputLen -= (temp == 1) ? TRAGET_TWO : 1; 163 break; 164 } else if (temp < i && valueType != Type::BASIC_URL_SAFE && valueType != Type::MIME_URL_SAFE) { 165 ret[index++] = searchArray[BIT_FLG]; 166 } else { 167 ret[index++] = searchArray[(bitWise >> ((TRAGET_THREE - i) * TRAGET_SIX)) & SIXTEEN_FLG]; 168 } 169 } 170 } 171 ret[index] = 0; 172 return ret; 173 } 174 175 /* base64 decode */ DecodeSync(napi_env env,napi_value src,Type valueType)176 napi_value Base64::DecodeSync(napi_env env, napi_value src, Type valueType) 177 { 178 bool resDecode = DecodeSyncInner(env, src, valueType); 179 if (!resDecode || pret == nullptr) { 180 return nullptr; 181 } 182 void *data = nullptr; 183 napi_value arrayBuffer = nullptr; 184 size_t bufferSize = decodeOutLen; 185 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 186 if (memcpy_s(data, bufferSize, reinterpret_cast<const void*>(pret), bufferSize) != EOK) { 187 FreeMemory(pret); 188 HILOG_ERROR("copy retDecode to arraybuffer error"); 189 return nullptr; 190 } 191 napi_value result = nullptr; 192 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 193 FreeMemory(pret); 194 return result; 195 } 196 DecodeSyncInner(napi_env env,napi_value src,Type valueType)197 bool Base64::DecodeSyncInner(napi_env env, napi_value src, Type valueType) 198 { 199 napi_valuetype valuetype = napi_undefined; 200 napi_typeof(env, src, &valuetype); 201 napi_typedarray_type type; 202 size_t length = 0; 203 void *resultData = nullptr; 204 char *inputString = nullptr; 205 if (valuetype != napi_valuetype::napi_string) { 206 napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr); 207 } 208 if (valuetype == napi_valuetype::napi_string) { 209 size_t prolen = 0; 210 napi_get_value_string_utf8(env, src, nullptr, 0, &prolen); 211 if (prolen > 0) { 212 inputString = new (std::nothrow) char[prolen + 1]; 213 if (inputString == nullptr) { 214 HILOG_ERROR("inputString is nullptr"); 215 return false; 216 } 217 if (memset_s(inputString, prolen + 1, '\0', prolen + 1) != EOK) { 218 FreeMemory(inputString); 219 napi_throw_error(env, "-1", "decode inputString memset_s failed"); 220 return false; 221 } 222 } else { 223 napi_throw_error(env, "-2", "prolen is error !"); 224 return false; 225 } 226 if (inputString != nullptr) { 227 napi_get_value_string_utf8(env, src, inputString, prolen + 1, &prolen); 228 pret = DecodeAchieve(env, inputString, prolen, valueType); 229 } 230 } else if (type == napi_typedarray_type::napi_uint8_array && length > 0) { 231 inputDecode_ = static_cast<const char*>(resultData); 232 pret = DecodeAchieve(env, inputDecode_, length, valueType); 233 } else { 234 std::string errMsg = 235 "Parameter error. The type of Parameter must be Uint8Array or string and the length greater than 0."; 236 napi_throw_error(env, "401", errMsg.c_str()); 237 return false; 238 } 239 FreeMemory(inputString); 240 return true; 241 } 242 DecodeAchieve(napi_env env,const char * input,size_t inputLen,Type valueType)243 unsigned char *Base64::DecodeAchieve(napi_env env, const char *input, size_t inputLen, Type valueType) 244 { 245 retLen = (inputLen / TRAGET_FOUR) * TRAGET_THREE; 246 decodeOutLen = retLen; 247 size_t equalCount = 0; 248 249 if (*(input + inputLen - 1) == '=') { 250 equalCount++; 251 } 252 if (*(input + inputLen - TRAGET_TWO) == '=') { 253 equalCount++; 254 } 255 retLen = DecodeOut(equalCount, retLen); 256 if (retLen > 0) { 257 retDecode = new (std::nothrow) unsigned char[retLen + 1]; 258 if (retDecode == nullptr) { 259 HILOG_ERROR("retDecode is nullptr"); 260 return nullptr; 261 } 262 if (memset_s(retDecode, retLen + 1, '\0', retLen + 1) != EOK) { 263 FreeMemory(retDecode); 264 napi_throw_error(env, "-1", "decode retDecode memset_s failed"); 265 return nullptr; 266 } 267 } else { 268 napi_throw_error(env, "-2", "retLen is error !"); 269 return nullptr; 270 } 271 if (retDecode == nullptr) { 272 return retDecode; 273 } 274 if (valueType == Type::BASIC_URL_SAFE || valueType == Type::MIME_URL_SAFE) { 275 size_t remainder = inputLen % TRAGET_FOUR; 276 if (remainder == TRAGET_TWO) { 277 decodeOutLen += 1; 278 } else if (remainder == TRAGET_THREE) { 279 decodeOutLen += TRAGET_TWO; 280 } 281 } 282 unsigned char *result = nullptr; 283 result = DecodeAchieveInner(env, input, inputLen, equalCount, valueType); 284 if (result == nullptr) { 285 FreeMemory(retDecode); 286 } 287 return result; 288 } 289 DecodeAchieveInner(napi_env env,const char * input,size_t inputLen,size_t equalCount,Type valueType)290 unsigned char *Base64::DecodeAchieveInner(napi_env env, const char *input, 291 size_t inputLen, size_t equalCount, Type valueType) 292 { 293 size_t index = 0; 294 size_t inp = 0; 295 size_t temp = 0; 296 size_t bitWise = 0; 297 while (inp < (inputLen - equalCount)) { 298 temp = 0; 299 bitWise = 0; 300 while (temp < TRAGET_FOUR) { 301 if (inp >= (inputLen - equalCount)) { 302 break; 303 } 304 int findsData = Finds(env, input[inp], valueType); 305 if (findsData == -1) { 306 return nullptr; 307 } 308 bitWise = (bitWise << TRAGET_SIX) | static_cast<size_t>(findsData); 309 inp++; 310 temp++; 311 } 312 bitWise = bitWise << ((TRAGET_FOUR - temp) * TRAGET_SIX); 313 for (size_t i = 0; i < TRAGET_THREE; i++) { 314 if (i == temp) { 315 break; 316 } 317 retDecode[index++] = static_cast<char>((bitWise >> ((TRAGET_TWO - i) * TRAGET_EIGHT)) & XFF_FLG); 318 } 319 } 320 retDecode[index] = 0; 321 return retDecode; 322 } 323 DecodeOut(size_t equalCount,size_t retLen)324 size_t Base64::DecodeOut(size_t equalCount, size_t retLen) 325 { 326 size_t temp = retLen; 327 switch (equalCount) { 328 case 0: 329 temp += TRAGET_FOUR; 330 break; 331 case 1: 332 temp += TRAGET_FOUR; 333 decodeOutLen -= 1; 334 break; 335 case TRAGET_TWO: 336 temp += TRAGET_THREE; 337 decodeOutLen -= TRAGET_TWO; 338 break; 339 default: 340 temp += TRAGET_TWO; 341 break; 342 } 343 return temp; 344 } 345 346 /* Decoding lookup function */ Finds(napi_env env,char ch,Type valueType)347 int Base64::Finds(napi_env env, char ch, Type valueType) 348 { 349 bool flag = false; 350 if (valueType == Type::BASIC_URL_SAFE || valueType == Type::MIME_URL_SAFE) { 351 flag = true; 352 } 353 int tableLen = flag ? TRAGET_SIXTYFIVE - 1 : TRAGET_SIXTYFIVE; 354 const char *searchArray = flag ? BASEURL : BASE; 355 for (int i = 0; i < tableLen; i++) { 356 if (searchArray[i] == ch) { 357 return i; 358 } 359 } 360 napi_throw_error(env, "-1", "The input string contains unsupported characters"); 361 return -1; 362 } 363 Encode(napi_env env,napi_value src,Type valueType)364 napi_value Base64::Encode(napi_env env, napi_value src, Type valueType) 365 { 366 napi_typedarray_type type; 367 size_t length = 0; 368 void *resultData = nullptr; 369 napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr); 370 if (type != napi_uint8_array || length == 0) { 371 napi_throw_error(env, "401", 372 "Parameter error. The type of Parameter must be Uint8Array and the length greater than zero."); 373 return nullptr; 374 } 375 unsigned char *inputEncode = nullptr; 376 inputEncode = static_cast<unsigned char*>(resultData); 377 CreateEncodePromise(env, inputEncode, length, valueType); 378 return stdEncodeInfo_->promise; 379 } 380 EncodeToString(napi_env env,napi_value src,Type valueType)381 napi_value Base64::EncodeToString(napi_env env, napi_value src, Type valueType) 382 { 383 napi_typedarray_type type; 384 size_t length = 0; 385 void *resultData = nullptr; 386 napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr); 387 if (type != napi_uint8_array || length == 0) { 388 napi_throw_error(env, "401", 389 "Parameter error. The type of Parameter must be Uint8Array and the length greater than zero."); 390 return nullptr; 391 } 392 unsigned char *inputEncode = nullptr; 393 inputEncode = static_cast<unsigned char*>(resultData); 394 CreateEncodeToStringPromise(env, inputEncode, length, valueType); 395 return stdEncodeInfo_->promise; 396 } 397 CreateEncodePromise(napi_env env,unsigned char * inputDecode,size_t length,Type valueType)398 void Base64::CreateEncodePromise(napi_env env, unsigned char *inputDecode, size_t length, Type valueType) 399 { 400 napi_value resourceName = nullptr; 401 stdEncodeInfo_ = new (std::nothrow) EncodeInfo(); 402 if (stdEncodeInfo_ == nullptr) { 403 HILOG_ERROR("stdEncodeInfo_ is nullptr"); 404 return; 405 } 406 stdEncodeInfo_->sinputEncode = inputDecode; 407 stdEncodeInfo_->slength = length; 408 stdEncodeInfo_->env = env; 409 stdEncodeInfo_->valueType = valueType; 410 napi_create_promise(env, &stdEncodeInfo_->deferred, &stdEncodeInfo_->promise); 411 napi_create_string_utf8(env, "ReadStdEncode", NAPI_AUTO_LENGTH, &resourceName); 412 napi_create_async_work(env, nullptr, resourceName, ReadStdEncode, EndStdEncode, 413 reinterpret_cast<void*>(stdEncodeInfo_), &stdEncodeInfo_->worker); 414 napi_queue_async_work_with_qos(env, stdEncodeInfo_->worker, napi_qos_user_initiated); 415 } 416 CreateEncodeToStringPromise(napi_env env,unsigned char * inputDecode,size_t length,Type valueType)417 void Base64::CreateEncodeToStringPromise(napi_env env, unsigned char *inputDecode, size_t length, Type valueType) 418 { 419 napi_value resourceName = nullptr; 420 stdEncodeInfo_ = new EncodeInfo(); 421 stdEncodeInfo_->sinputEncode = inputDecode; 422 stdEncodeInfo_->slength = length; 423 stdEncodeInfo_->valueType = valueType; 424 napi_create_promise(env, &stdEncodeInfo_->deferred, &stdEncodeInfo_->promise); 425 napi_create_string_utf8(env, "ReadStdEncodeToString", NAPI_AUTO_LENGTH, &resourceName); 426 napi_create_async_work(env, nullptr, resourceName, ReadStdEncodeToString, EndStdEncodeToString, 427 reinterpret_cast<void*>(stdEncodeInfo_), &stdEncodeInfo_->worker); 428 napi_queue_async_work_with_qos(env, stdEncodeInfo_->worker, napi_qos_user_initiated); 429 } 430 EncodeAchieves(napi_env env,EncodeInfo * encodeInfo)431 unsigned char *EncodeAchieves(napi_env env, EncodeInfo *encodeInfo) 432 { 433 const unsigned char *input = encodeInfo->sinputEncode; 434 size_t inputLen = encodeInfo->slength; 435 unsigned char *ret = nullptr; 436 437 size_t outputLen = 0; 438 outputLen = (inputLen / TRAGET_THREE) * TRAGET_FOUR; 439 if ((inputLen % TRAGET_THREE) > 0) { 440 outputLen += TRAGET_FOUR; 441 } 442 encodeInfo->soutputLen = outputLen; 443 if (outputLen > 0) { 444 ret = new unsigned char[outputLen + 1]; 445 if (memset_s(ret, outputLen + 1, '\0', outputLen + 1) != EOK) { 446 FreeMemory(ret); 447 napi_throw_error(encodeInfo->env, "-1", "ret path memset_s failed"); 448 return nullptr; 449 } 450 } else { 451 napi_throw_error(encodeInfo->env, "-2", "outputLen is error !"); 452 return nullptr; 453 } 454 if (ret == nullptr) { 455 return ret; 456 } 457 458 bool flag = false; 459 if (encodeInfo->valueType == Type::BASIC_URL_SAFE || encodeInfo->valueType == Type::MIME_URL_SAFE) { 460 flag = true; 461 } 462 const char *searchArray = flag ? BASEURL : BASE; 463 unsigned char *result = nullptr; 464 result = EncodeAchievesInner(ret, encodeInfo, searchArray, inputLen, input); 465 return result; 466 } 467 EncodeAchievesInner(unsigned char * ret,EncodeInfo * encodeInfo,const char * searchArray,size_t inputLen,const unsigned char * input)468 unsigned char *EncodeAchievesInner(unsigned char *ret, EncodeInfo *encodeInfo, 469 const char *searchArray, size_t inputLen, const unsigned char *input) 470 { 471 size_t inp = 0; 472 size_t temp = 0; 473 size_t bitWise = 0; 474 size_t index = 0; 475 while (inp < inputLen) { 476 temp = 0; 477 bitWise = 0; 478 while (temp < TRAGET_THREE) { 479 if (inp >= inputLen) { 480 break; 481 } 482 bitWise = ((bitWise << TRAGET_EIGHT) | (input[inp] & XFF_FLG)); 483 inp++; 484 temp++; 485 } 486 bitWise = (bitWise << ((TRAGET_THREE - temp) * TRAGET_EIGHT)); 487 for (size_t i = 0; i < TRAGET_FOUR; i++) { 488 if (temp < i && 489 (encodeInfo->valueType == Type::BASIC_URL_SAFE || encodeInfo->valueType == Type::MIME_URL_SAFE)) { 490 encodeInfo->soutputLen -= (temp == 1) ? TRAGET_TWO : 1; 491 break; 492 } else if (temp < i && 493 (encodeInfo->valueType != Type::BASIC_URL_SAFE && encodeInfo->valueType != Type::MIME_URL_SAFE)) { 494 ret[index++] = searchArray[BIT_FLG]; 495 } else { 496 ret[index++] = searchArray[(bitWise >> ((TRAGET_THREE - i) * TRAGET_SIX)) & SIXTEEN_FLG]; 497 } 498 } 499 } 500 ret[index] = 0; 501 return ret; 502 } 503 ReadStdEncode(napi_env env,void * data)504 void Base64::ReadStdEncode(napi_env env, void *data) 505 { 506 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(data); 507 unsigned char *rets = EncodeAchieves(env, stdEncodeInfo); 508 stdEncodeInfo->sinputEncoding = rets; 509 } 510 EndStdEncode(napi_env env,napi_status status,void * buffer)511 void Base64::EndStdEncode(napi_env env, napi_status status, void *buffer) 512 { 513 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(buffer); 514 void *data = nullptr; 515 napi_handle_scope scope = nullptr; 516 napi_open_handle_scope(env, &scope); 517 if (scope == nullptr) { 518 return; 519 } 520 napi_value arrayBuffer = nullptr; 521 size_t bufferSize = stdEncodeInfo->soutputLen; 522 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 523 if (memcpy_s(data, bufferSize, 524 reinterpret_cast<const void*>(stdEncodeInfo->sinputEncoding), bufferSize) != EOK) { 525 HILOG_ERROR("copy ret to arraybuffer error"); 526 napi_delete_async_work(env, stdEncodeInfo->worker); 527 napi_close_handle_scope(env, scope); 528 return; 529 } 530 napi_value result = nullptr; 531 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 532 napi_resolve_deferred(env, stdEncodeInfo->deferred, result); 533 napi_delete_async_work(env, stdEncodeInfo->worker); 534 napi_close_handle_scope(env, scope); 535 delete[] stdEncodeInfo->sinputEncoding; 536 delete stdEncodeInfo; 537 } 538 ReadStdEncodeToString(napi_env env,void * data)539 void Base64::ReadStdEncodeToString(napi_env env, void *data) 540 { 541 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(data); 542 unsigned char *rets = EncodeAchieves(env, stdEncodeInfo); 543 stdEncodeInfo->sinputEncoding = rets; 544 } 545 EndStdEncodeToString(napi_env env,napi_status status,void * buffer)546 void Base64::EndStdEncodeToString(napi_env env, napi_status status, void *buffer) 547 { 548 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(buffer); 549 napi_handle_scope scope = nullptr; 550 napi_open_handle_scope(env, &scope); 551 if (scope == nullptr) { 552 return; 553 } 554 const char *encString = reinterpret_cast<const char*>(stdEncodeInfo->sinputEncoding); 555 napi_value resultStr = nullptr; 556 napi_create_string_utf8(env, encString, strlen(encString), &resultStr); 557 napi_resolve_deferred(env, stdEncodeInfo->deferred, resultStr); 558 napi_delete_async_work(env, stdEncodeInfo->worker); 559 napi_close_handle_scope(env, scope); 560 delete[] stdEncodeInfo->sinputEncoding; 561 delete stdEncodeInfo; 562 } 563 Decode(napi_env env,napi_value src,Type valueType)564 napi_value Base64::Decode(napi_env env, napi_value src, Type valueType) 565 { 566 napi_valuetype valuetype = napi_undefined; 567 napi_typeof(env, src, &valuetype); 568 napi_typedarray_type type; 569 size_t length = 0; 570 void *resultData = nullptr; 571 char *inputString = nullptr; 572 char *inputDecode = nullptr; 573 if (valuetype != napi_valuetype::napi_string) { 574 if (napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr) != napi_ok) { 575 std::string errMsg = 576 "Parameter error. The type of Parameter must be Uint8Array or string."; 577 napi_throw_error(env, "401", errMsg.c_str()); 578 return nullptr; 579 } 580 } 581 if (valuetype == napi_valuetype::napi_string) { 582 size_t prolen = 0; 583 napi_get_value_string_utf8(env, src, nullptr, 0, &prolen); 584 if (prolen > 0) { 585 inputString = new char[prolen + 1]; 586 if (memset_s(inputString, prolen + 1, '\0', prolen + 1) != EOK) { 587 napi_throw_error(env, "-1", "decode inputString memset_s failed"); 588 return nullptr; 589 } 590 } else { 591 napi_throw_error(env, "-2", "prolen is error !"); 592 return nullptr; 593 } 594 napi_get_value_string_utf8(env, src, inputString, prolen + 1, &prolen); 595 CreateDecodePromise(env, inputString, prolen, valueType); 596 } else if (type == napi_typedarray_type::napi_uint8_array && length > 0) { 597 inputDecode = static_cast<char*>(resultData); 598 CreateDecodePromise(env, inputDecode, length, valueType); 599 } else { 600 std::string errMsg = 601 "Parameter error. The type of Parameter must be Uint8Array or string and the length greater than 0."; 602 napi_throw_error(env, "401", errMsg.c_str()); 603 FreeMemory(inputString); 604 return nullptr; 605 } 606 return stdDecodeInfo_->promise; 607 } 608 CreateDecodePromise(napi_env env,char * inputDecode,size_t length,Type valueType)609 void Base64::CreateDecodePromise(napi_env env, char *inputDecode, size_t length, Type valueType) 610 { 611 napi_value resourceName = nullptr; 612 stdDecodeInfo_ = new DecodeInfo(); 613 stdDecodeInfo_->sinputDecode = inputDecode; 614 stdDecodeInfo_->slength = length; 615 stdDecodeInfo_->env = env; 616 stdDecodeInfo_->valueType = valueType; 617 napi_create_promise(env, &stdDecodeInfo_->deferred, &stdDecodeInfo_->promise); 618 napi_create_string_utf8(env, "ReadStdDecode", NAPI_AUTO_LENGTH, &resourceName); 619 napi_create_async_work(env, nullptr, resourceName, ReadStdDecode, EndStdDecode, 620 reinterpret_cast<void*>(stdDecodeInfo_), &stdDecodeInfo_->worker); 621 napi_queue_async_work_with_qos(env, stdDecodeInfo_->worker, napi_qos_user_initiated); 622 } 623 Finds(char ch,Type valueType)624 int Finds(char ch, Type valueType) 625 { 626 bool flag = false; 627 if (valueType == Type::BASIC_URL_SAFE || valueType == Type::MIME_URL_SAFE) { 628 flag = true; 629 } 630 int tableLen = flag ? TRAGET_SIXTYFIVE - 1 : TRAGET_SIXTYFIVE; 631 const char *searchArray = flag ? BASEURL : BASE; 632 int couts = 0; 633 for (int i = 0; i < tableLen; i++) { 634 if (searchArray[i] == ch) { 635 couts = i; 636 } 637 } 638 return couts; 639 } 640 DecodeOut(size_t equalCount,size_t retLen,DecodeInfo * decodeInfo)641 size_t DecodeOut(size_t equalCount, size_t retLen, DecodeInfo *decodeInfo) 642 { 643 switch (equalCount) { 644 case 0: 645 retLen += TRAGET_FOUR; 646 break; 647 case 1: 648 retLen += TRAGET_FOUR; 649 decodeInfo->decodeOutLen -= 1; 650 break; 651 case TRAGET_TWO: 652 retLen += TRAGET_THREE; 653 decodeInfo->decodeOutLen -= TRAGET_TWO; 654 break; 655 default: 656 retLen += TRAGET_TWO; 657 break; 658 } 659 return retLen; 660 } 661 DecodeAchieves(napi_env env,DecodeInfo * decodeInfo)662 unsigned char *DecodeAchieves(napi_env env, DecodeInfo *decodeInfo) 663 { 664 const char *input = decodeInfo->sinputDecode; 665 size_t inputLen = decodeInfo->slength; 666 size_t retLen = 0; 667 retLen = (inputLen / TRAGET_FOUR) * TRAGET_THREE; 668 decodeInfo->decodeOutLen = retLen; 669 size_t equalCount = 0; 670 unsigned char *retDecode = nullptr; 671 if (*(input + inputLen - 1) == '=') { 672 equalCount++; 673 } 674 if (*(input + inputLen - TRAGET_TWO) == '=') { 675 equalCount++; 676 } 677 retLen = DecodeOut(equalCount, retLen, decodeInfo); 678 if (retLen > 0) { 679 retDecode = new unsigned char[retLen + 1]; 680 if (memset_s(retDecode, retLen + 1, '\0', retLen + 1) != EOK) { 681 FreeMemory(retDecode); 682 napi_throw_error(decodeInfo->env, "-1", "decode retDecode memset_s failed"); 683 return nullptr; 684 } 685 } else { 686 napi_throw_error(decodeInfo->env, "-2", "retLen is error !"); 687 return nullptr; 688 } 689 if (decodeInfo->valueType == Type::BASIC_URL_SAFE || decodeInfo->valueType == Type::MIME_URL_SAFE) { 690 size_t remainder = inputLen % TRAGET_FOUR; 691 if (remainder == TRAGET_TWO) { 692 decodeInfo->decodeOutLen += 1; 693 } else if (remainder == TRAGET_THREE) { 694 decodeInfo->decodeOutLen += TRAGET_TWO; 695 } 696 } 697 698 unsigned char *result = nullptr; 699 result = DecodeAchievesInner(inputLen, equalCount, input, decodeInfo, retDecode); 700 if (result == nullptr) { 701 FreeMemory(retDecode); 702 } 703 return result; 704 } 705 DecodeAchievesInner(size_t inputLen,size_t equalCount,const char * input,DecodeInfo * decodeInfo,unsigned char * retDecode)706 unsigned char *DecodeAchievesInner(size_t inputLen, size_t equalCount, 707 const char *input, DecodeInfo *decodeInfo, unsigned char *retDecode) 708 { 709 size_t inp = 0; 710 size_t temp = 0; 711 size_t bitWise = 0; 712 size_t index = 0; 713 while (inp < (inputLen - equalCount)) { 714 temp = 0; 715 bitWise = 0; 716 while (temp < TRAGET_FOUR) { 717 if (inp >= (inputLen - equalCount)) { 718 break; 719 } 720 int findData = Finds(input[inp], decodeInfo->valueType); 721 if (findData == -1) { 722 return nullptr; 723 } 724 bitWise = (bitWise << TRAGET_SIX) | static_cast<size_t>(findData); 725 inp++; 726 temp++; 727 } 728 bitWise = bitWise << ((TRAGET_FOUR - temp) * TRAGET_SIX); 729 for (size_t i = 0; i < TRAGET_THREE; i++) { 730 if (i == temp) { 731 break; 732 } 733 retDecode[index++] = static_cast<char>((bitWise >> ((TRAGET_TWO - i) * TRAGET_EIGHT)) & XFF_FLG); 734 } 735 } 736 retDecode[index] = 0; 737 return retDecode; 738 } 739 ReadStdDecode(napi_env env,void * data)740 void Base64::ReadStdDecode(napi_env env, void *data) 741 { 742 auto stdDecodeInfo = reinterpret_cast<DecodeInfo*>(data); 743 unsigned char *rets = DecodeAchieves(env, stdDecodeInfo); 744 stdDecodeInfo->sinputDecoding = rets; 745 } EndStdDecode(napi_env env,napi_status status,void * buffer)746 void Base64::EndStdDecode(napi_env env, napi_status status, void *buffer) 747 { 748 auto stdDecodeInfo = reinterpret_cast<DecodeInfo*>(buffer); 749 void *data = nullptr; 750 napi_handle_scope scope = nullptr; 751 napi_open_handle_scope(env, &scope); 752 if (scope == nullptr) { 753 return; 754 } 755 napi_value arrayBuffer = nullptr; 756 size_t bufferSize = stdDecodeInfo->decodeOutLen; 757 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 758 if (memcpy_s(data, bufferSize, 759 reinterpret_cast<const void*>(stdDecodeInfo->sinputDecoding), bufferSize) != EOK) { 760 HILOG_ERROR("copy ret to arraybuffer error"); 761 napi_delete_async_work(env, stdDecodeInfo->worker); 762 napi_close_handle_scope(env, scope); 763 return; 764 } 765 napi_value result = nullptr; 766 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 767 napi_resolve_deferred(env, stdDecodeInfo->deferred, result); 768 napi_delete_async_work(env, stdDecodeInfo->worker); 769 napi_close_handle_scope(env, scope); 770 delete[] stdDecodeInfo->sinputDecoding; 771 delete stdDecodeInfo; 772 } 773 774 /* Memory cleanup function */ FreeMemory(char * & address)775 void FreeMemory(char *&address) 776 { 777 if (address != nullptr) { 778 delete[] address; 779 address = nullptr; 780 } 781 } FreeMemory(unsigned char * & address)782 void FreeMemory(unsigned char *&address) 783 { 784 if (address != nullptr) { 785 delete[] address; 786 address = nullptr; 787 } 788 } 789 } 790