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); 375 return stdEncodeInfo_->promise; 376 } 377 EncodeToString(napi_env env,napi_value src,Type valueType)378 napi_value Base64::EncodeToString(napi_env env, napi_value src, Type valueType) 379 { 380 napi_typedarray_type type; 381 size_t length = 0; 382 void *resultData = nullptr; 383 napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr); 384 if (type != napi_uint8_array || length == 0) { 385 napi_throw_error(env, "401", 386 "Parameter error. The type of Parameter must be Uint8Array and the length greater than zero."); 387 return nullptr; 388 } 389 unsigned char *inputEncode = nullptr; 390 inputEncode = static_cast<unsigned char*>(resultData); 391 CreateEncodeToStringPromise(env, inputEncode, length, valueType); 392 return stdEncodeInfo_->promise; 393 } 394 CreateEncodePromise(napi_env env,unsigned char * inputDecode,size_t length,Type valueType)395 void Base64::CreateEncodePromise(napi_env env, unsigned char *inputDecode, size_t length, Type valueType) 396 { 397 napi_value resourceName = nullptr; 398 stdEncodeInfo_ = new (std::nothrow) EncodeInfo(); 399 if (stdEncodeInfo_ == nullptr) { 400 HILOG_ERROR("Base64:: memory allocation failed, stdEncodeInfo_ is nullptr"); 401 return; 402 } 403 stdEncodeInfo_->sinputEncode = inputDecode; 404 stdEncodeInfo_->slength = length; 405 stdEncodeInfo_->env = env; 406 stdEncodeInfo_->valueType = valueType; 407 napi_create_promise(env, &stdEncodeInfo_->deferred, &stdEncodeInfo_->promise); 408 napi_create_string_utf8(env, "ReadStdEncode", NAPI_AUTO_LENGTH, &resourceName); 409 napi_create_async_work(env, nullptr, resourceName, ReadStdEncode, EndStdEncode, 410 reinterpret_cast<void*>(stdEncodeInfo_), &stdEncodeInfo_->worker); 411 napi_queue_async_work_with_qos(env, stdEncodeInfo_->worker, napi_qos_user_initiated); 412 } 413 CreateEncodeToStringPromise(napi_env env,unsigned char * inputDecode,size_t length,Type valueType)414 void Base64::CreateEncodeToStringPromise(napi_env env, unsigned char *inputDecode, size_t length, Type valueType) 415 { 416 napi_value resourceName = nullptr; 417 stdEncodeInfo_ = new EncodeInfo(); 418 stdEncodeInfo_->sinputEncode = inputDecode; 419 stdEncodeInfo_->slength = length; 420 stdEncodeInfo_->valueType = valueType; 421 napi_create_promise(env, &stdEncodeInfo_->deferred, &stdEncodeInfo_->promise); 422 napi_create_string_utf8(env, "ReadStdEncodeToString", NAPI_AUTO_LENGTH, &resourceName); 423 napi_create_async_work(env, nullptr, resourceName, ReadStdEncodeToString, EndStdEncodeToString, 424 reinterpret_cast<void*>(stdEncodeInfo_), &stdEncodeInfo_->worker); 425 napi_queue_async_work_with_qos(env, stdEncodeInfo_->worker, napi_qos_user_initiated); 426 } 427 EncodeAchieves(napi_env env,EncodeInfo * encodeInfo)428 unsigned char *EncodeAchieves(napi_env env, EncodeInfo *encodeInfo) 429 { 430 const unsigned char *input = encodeInfo->sinputEncode; 431 size_t inputLen = encodeInfo->slength; 432 unsigned char *ret = nullptr; 433 434 size_t outputLen = 0; 435 outputLen = (inputLen / TRAGET_THREE) * TRAGET_FOUR; 436 if ((inputLen % TRAGET_THREE) > 0) { 437 outputLen += TRAGET_FOUR; 438 } 439 encodeInfo->soutputLen = outputLen; 440 if (outputLen > 0) { 441 ret = new unsigned char[outputLen + 1]; 442 if (memset_s(ret, outputLen + 1, '\0', outputLen + 1) != EOK) { 443 FreeMemory(ret); 444 napi_throw_error(encodeInfo->env, "-1", "ret path memset_s failed"); 445 return nullptr; 446 } 447 } else { 448 napi_throw_error(encodeInfo->env, "-2", "outputLen is error !"); 449 return nullptr; 450 } 451 if (ret == nullptr) { 452 return ret; 453 } 454 455 bool flag = false; 456 if (encodeInfo->valueType == Type::BASIC_URL_SAFE || encodeInfo->valueType == Type::MIME_URL_SAFE) { 457 flag = true; 458 } 459 const char *searchArray = flag ? BASEURL : BASE; 460 unsigned char *result = nullptr; 461 result = EncodeAchievesInner(ret, encodeInfo, searchArray, inputLen, input); 462 return result; 463 } 464 EncodeAchievesInner(unsigned char * ret,EncodeInfo * encodeInfo,const char * searchArray,size_t inputLen,const unsigned char * input)465 unsigned char *EncodeAchievesInner(unsigned char *ret, EncodeInfo *encodeInfo, 466 const char *searchArray, size_t inputLen, const unsigned char *input) 467 { 468 size_t inp = 0; 469 size_t temp = 0; 470 size_t bitWise = 0; 471 size_t index = 0; 472 while (inp < inputLen) { 473 temp = 0; 474 bitWise = 0; 475 while (temp < TRAGET_THREE) { 476 if (inp >= inputLen) { 477 break; 478 } 479 bitWise = ((bitWise << TRAGET_EIGHT) | (input[inp] & XFF_FLG)); 480 inp++; 481 temp++; 482 } 483 bitWise = (bitWise << ((TRAGET_THREE - temp) * TRAGET_EIGHT)); 484 for (size_t i = 0; i < TRAGET_FOUR; i++) { 485 if (temp < i && 486 (encodeInfo->valueType == Type::BASIC_URL_SAFE || encodeInfo->valueType == Type::MIME_URL_SAFE)) { 487 encodeInfo->soutputLen -= (temp == 1) ? TRAGET_TWO : 1; 488 break; 489 } else if (temp < i && 490 (encodeInfo->valueType != Type::BASIC_URL_SAFE && encodeInfo->valueType != Type::MIME_URL_SAFE)) { 491 ret[index++] = searchArray[BIT_FLG]; 492 } else { 493 ret[index++] = searchArray[(bitWise >> ((TRAGET_THREE - i) * TRAGET_SIX)) & SIXTEEN_FLG]; 494 } 495 } 496 } 497 ret[index] = 0; 498 return ret; 499 } 500 ReadStdEncode(napi_env env,void * data)501 void Base64::ReadStdEncode(napi_env env, void *data) 502 { 503 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(data); 504 unsigned char *rets = EncodeAchieves(env, stdEncodeInfo); 505 stdEncodeInfo->sinputEncoding = rets; 506 } 507 EndStdEncode(napi_env env,napi_status status,void * buffer)508 void Base64::EndStdEncode(napi_env env, napi_status status, void *buffer) 509 { 510 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(buffer); 511 void *data = nullptr; 512 napi_handle_scope scope = nullptr; 513 napi_open_handle_scope(env, &scope); 514 if (scope == nullptr) { 515 return; 516 } 517 napi_value arrayBuffer = nullptr; 518 size_t bufferSize = stdEncodeInfo->soutputLen; 519 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 520 if (memcpy_s(data, bufferSize, 521 reinterpret_cast<const void*>(stdEncodeInfo->sinputEncoding), bufferSize) != EOK) { 522 HILOG_ERROR("Base64:: copy ret to arraybuffer error"); 523 napi_delete_async_work(env, stdEncodeInfo->worker); 524 napi_close_handle_scope(env, scope); 525 return; 526 } 527 napi_value result = nullptr; 528 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 529 napi_resolve_deferred(env, stdEncodeInfo->deferred, result); 530 napi_delete_async_work(env, stdEncodeInfo->worker); 531 napi_close_handle_scope(env, scope); 532 delete[] stdEncodeInfo->sinputEncoding; 533 delete stdEncodeInfo; 534 } 535 ReadStdEncodeToString(napi_env env,void * data)536 void Base64::ReadStdEncodeToString(napi_env env, void *data) 537 { 538 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(data); 539 unsigned char *rets = EncodeAchieves(env, stdEncodeInfo); 540 stdEncodeInfo->sinputEncoding = rets; 541 } 542 EndStdEncodeToString(napi_env env,napi_status status,void * buffer)543 void Base64::EndStdEncodeToString(napi_env env, napi_status status, void *buffer) 544 { 545 auto stdEncodeInfo = reinterpret_cast<EncodeInfo*>(buffer); 546 napi_handle_scope scope = nullptr; 547 napi_open_handle_scope(env, &scope); 548 if (scope == nullptr) { 549 return; 550 } 551 const char *encString = reinterpret_cast<const char*>(stdEncodeInfo->sinputEncoding); 552 napi_value resultStr = nullptr; 553 napi_create_string_utf8(env, encString, strlen(encString), &resultStr); 554 napi_resolve_deferred(env, stdEncodeInfo->deferred, resultStr); 555 napi_delete_async_work(env, stdEncodeInfo->worker); 556 napi_close_handle_scope(env, scope); 557 delete[] stdEncodeInfo->sinputEncoding; 558 delete stdEncodeInfo; 559 } 560 Decode(napi_env env,napi_value src,Type valueType)561 napi_value Base64::Decode(napi_env env, napi_value src, Type valueType) 562 { 563 napi_valuetype valuetype = napi_undefined; 564 napi_typeof(env, src, &valuetype); 565 napi_typedarray_type type; 566 size_t length = 0; 567 void *resultData = nullptr; 568 char *inputString = nullptr; 569 char *inputDecode = nullptr; 570 if (valuetype != napi_valuetype::napi_string) { 571 if (napi_get_typedarray_info(env, src, &type, &length, &resultData, nullptr, nullptr) != napi_ok) { 572 std::string errMsg = 573 "Parameter error. The type of Parameter must be Uint8Array or string."; 574 napi_throw_error(env, "401", errMsg.c_str()); 575 return nullptr; 576 } 577 } 578 if (valuetype == napi_valuetype::napi_string) { 579 size_t prolen = 0; 580 napi_get_value_string_utf8(env, src, nullptr, 0, &prolen); 581 if (prolen > 0) { 582 inputString = new char[prolen + 1]; 583 if (memset_s(inputString, prolen + 1, '\0', prolen + 1) != EOK) { 584 delete[] inputString; 585 napi_throw_error(env, "-1", "decode inputString memset_s failed"); 586 return nullptr; 587 } 588 } else { 589 napi_throw_error(env, "-2", "prolen is error !"); 590 return nullptr; 591 } 592 napi_get_value_string_utf8(env, src, inputString, prolen + 1, &prolen); 593 CreateDecodePromise(env, inputString, prolen, valueType); 594 } else if (type == napi_typedarray_type::napi_uint8_array && length > 0) { 595 inputDecode = static_cast<char*>(resultData); 596 CreateDecodePromise(env, inputDecode, length, valueType); 597 } else { 598 std::string errMsg = 599 "Parameter error. The type of Parameter must be Uint8Array or string and the length greater than 0."; 600 napi_throw_error(env, "401", errMsg.c_str()); 601 FreeMemory(inputString); 602 return nullptr; 603 } 604 return stdDecodeInfo_->promise; 605 } 606 CreateDecodePromise(napi_env env,char * inputDecode,size_t length,Type valueType)607 void Base64::CreateDecodePromise(napi_env env, char *inputDecode, size_t length, Type valueType) 608 { 609 napi_value resourceName = nullptr; 610 stdDecodeInfo_ = new DecodeInfo(); 611 stdDecodeInfo_->sinputDecode = inputDecode; 612 stdDecodeInfo_->slength = length; 613 stdDecodeInfo_->env = env; 614 stdDecodeInfo_->valueType = valueType; 615 napi_create_promise(env, &stdDecodeInfo_->deferred, &stdDecodeInfo_->promise); 616 napi_create_string_utf8(env, "ReadStdDecode", NAPI_AUTO_LENGTH, &resourceName); 617 napi_create_async_work(env, nullptr, resourceName, ReadStdDecode, EndStdDecode, 618 reinterpret_cast<void*>(stdDecodeInfo_), &stdDecodeInfo_->worker); 619 napi_queue_async_work_with_qos(env, stdDecodeInfo_->worker, napi_qos_user_initiated); 620 } 621 Finds(char ch,Type valueType)622 int Finds(char ch, Type valueType) 623 { 624 bool flag = false; 625 if (valueType == Type::BASIC_URL_SAFE || valueType == Type::MIME_URL_SAFE) { 626 flag = true; 627 } 628 int tableLen = flag ? TRAGET_SIXTYFIVE - 1 : TRAGET_SIXTYFIVE; 629 const char *searchArray = flag ? BASEURL : BASE; 630 int couts = 0; 631 for (int i = 0; i < tableLen; i++) { 632 if (searchArray[i] == ch) { 633 couts = i; 634 } 635 } 636 return couts; 637 } 638 DecodeOut(size_t equalCount,size_t retLen,DecodeInfo * decodeInfo)639 size_t DecodeOut(size_t equalCount, size_t retLen, DecodeInfo *decodeInfo) 640 { 641 switch (equalCount) { 642 case 0: 643 retLen += TRAGET_FOUR; 644 break; 645 case 1: 646 retLen += TRAGET_FOUR; 647 decodeInfo->decodeOutLen -= 1; 648 break; 649 case TRAGET_TWO: 650 retLen += TRAGET_THREE; 651 decodeInfo->decodeOutLen -= TRAGET_TWO; 652 break; 653 default: 654 retLen += TRAGET_TWO; 655 break; 656 } 657 return retLen; 658 } 659 DecodeAchieves(napi_env env,DecodeInfo * decodeInfo)660 unsigned char *DecodeAchieves(napi_env env, DecodeInfo *decodeInfo) 661 { 662 const char *input = decodeInfo->sinputDecode; 663 size_t inputLen = decodeInfo->slength; 664 size_t retLen = 0; 665 retLen = (inputLen / TRAGET_FOUR) * TRAGET_THREE; 666 decodeInfo->decodeOutLen = retLen; 667 size_t equalCount = 0; 668 unsigned char *retDecode = nullptr; 669 if (*(input + inputLen - 1) == '=') { 670 equalCount++; 671 } 672 if (*(input + inputLen - TRAGET_TWO) == '=') { 673 equalCount++; 674 } 675 retLen = DecodeOut(equalCount, retLen, decodeInfo); 676 if (retLen > 0) { 677 retDecode = new unsigned char[retLen + 1]; 678 if (memset_s(retDecode, retLen + 1, '\0', retLen + 1) != EOK) { 679 FreeMemory(retDecode); 680 napi_throw_error(decodeInfo->env, "-1", "decode retDecode memset_s failed"); 681 return nullptr; 682 } 683 } else { 684 napi_throw_error(decodeInfo->env, "-2", "retLen is error !"); 685 return nullptr; 686 } 687 if (decodeInfo->valueType == Type::BASIC_URL_SAFE || decodeInfo->valueType == Type::MIME_URL_SAFE) { 688 size_t remainder = inputLen % TRAGET_FOUR; 689 if (remainder == TRAGET_TWO) { 690 decodeInfo->decodeOutLen += 1; 691 } else if (remainder == TRAGET_THREE) { 692 decodeInfo->decodeOutLen += TRAGET_TWO; 693 } 694 } 695 696 unsigned char *result = nullptr; 697 result = DecodeAchievesInner(inputLen, equalCount, input, decodeInfo, retDecode); 698 if (result == nullptr) { 699 FreeMemory(retDecode); 700 } 701 return result; 702 } 703 DecodeAchievesInner(size_t inputLen,size_t equalCount,const char * input,DecodeInfo * decodeInfo,unsigned char * retDecode)704 unsigned char *DecodeAchievesInner(size_t inputLen, size_t equalCount, 705 const char *input, DecodeInfo *decodeInfo, unsigned char *retDecode) 706 { 707 size_t inp = 0; 708 size_t temp = 0; 709 size_t bitWise = 0; 710 size_t index = 0; 711 while (inp < (inputLen - equalCount)) { 712 temp = 0; 713 bitWise = 0; 714 while (temp < TRAGET_FOUR) { 715 if (inp >= (inputLen - equalCount)) { 716 break; 717 } 718 int findData = Finds(input[inp], decodeInfo->valueType); 719 if (findData == -1) { 720 return nullptr; 721 } 722 bitWise = (bitWise << TRAGET_SIX) | static_cast<size_t>(findData); 723 inp++; 724 temp++; 725 } 726 bitWise = bitWise << ((TRAGET_FOUR - temp) * TRAGET_SIX); 727 for (size_t i = 0; i < TRAGET_THREE; i++) { 728 if (i == temp) { 729 break; 730 } 731 retDecode[index++] = static_cast<char>((bitWise >> ((TRAGET_TWO - i) * TRAGET_EIGHT)) & XFF_FLG); 732 } 733 } 734 retDecode[index] = 0; 735 return retDecode; 736 } 737 ReadStdDecode(napi_env env,void * data)738 void Base64::ReadStdDecode(napi_env env, void *data) 739 { 740 auto stdDecodeInfo = reinterpret_cast<DecodeInfo*>(data); 741 unsigned char *rets = DecodeAchieves(env, stdDecodeInfo); 742 stdDecodeInfo->sinputDecoding = rets; 743 } EndStdDecode(napi_env env,napi_status status,void * buffer)744 void Base64::EndStdDecode(napi_env env, napi_status status, void *buffer) 745 { 746 auto stdDecodeInfo = reinterpret_cast<DecodeInfo*>(buffer); 747 void *data = nullptr; 748 napi_handle_scope scope = nullptr; 749 napi_open_handle_scope(env, &scope); 750 if (scope == nullptr) { 751 return; 752 } 753 napi_value arrayBuffer = nullptr; 754 size_t bufferSize = stdDecodeInfo->decodeOutLen; 755 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 756 if (memcpy_s(data, bufferSize, 757 reinterpret_cast<const void*>(stdDecodeInfo->sinputDecoding), bufferSize) != EOK) { 758 HILOG_ERROR("Base64:: copy ret to arraybuffer error"); 759 int32_t errCode = 401; // 401:errCode 760 const char* errMessage = 761 "Parameter error. The type of the parameter must be a string and must be valid and legal"; 762 napi_value error = Tools::ErrorHelper::CreateError(env, errCode, errMessage); 763 napi_reject_deferred(env, stdDecodeInfo->deferred, error); 764 napi_delete_async_work(env, stdDecodeInfo->worker); 765 napi_close_handle_scope(env, scope); 766 return; 767 } 768 napi_value result = nullptr; 769 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 770 napi_resolve_deferred(env, stdDecodeInfo->deferred, result); 771 napi_delete_async_work(env, stdDecodeInfo->worker); 772 napi_close_handle_scope(env, scope); 773 delete[] stdDecodeInfo->sinputDecoding; 774 delete stdDecodeInfo; 775 } 776 777 /* Memory cleanup function */ FreeMemory(char * & address)778 void FreeMemory(char *&address) 779 { 780 if (address != nullptr) { 781 delete[] address; 782 address = nullptr; 783 } 784 } FreeMemory(unsigned char * & address)785 void FreeMemory(unsigned char *&address) 786 { 787 if (address != nullptr) { 788 delete[] address; 789 address = nullptr; 790 } 791 } 792 } 793