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