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_textdecoder.h" 17 #include <algorithm> 18 #include <codecvt> 19 20 #include <locale> 21 #include <map> 22 #include <string> 23 #include <vector> 24 25 #include "ohos/init_data.h" 26 #include "securec.h" 27 #include "unicode/unistr.h" 28 #include "utils/log.h" 29 #include "util_helper.h" 30 31 namespace OHOS::Util { 32 using namespace Commonlibrary::Platform; 33 TextDecoder(const std::string & buff,std::vector<int> optionVec)34 TextDecoder::TextDecoder(const std::string &buff, std::vector<int> optionVec) 35 : label_(0), encStr_(buff), tranTool_(nullptr, nullptr) 36 { 37 uint32_t i32Flag = 0; 38 if (optionVec.size() == 2) { // 2:Meaning of optionVec size 2 39 if (optionVec[0] >= 0 && optionVec[1] >= 0) { 40 i32Flag |= optionVec[0] ? static_cast<uint32_t>(ConverterFlags::FATAL_FLG) : 0; 41 i32Flag |= optionVec[1] ? static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG) : 0; 42 } else if (optionVec[0] >= 0 && optionVec[1] < 0) { 43 i32Flag |= optionVec[0] ? static_cast<uint32_t>(ConverterFlags::FATAL_FLG) : 0; 44 } else if (optionVec[0] < 0 && optionVec[1] >= 0) { 45 i32Flag |= optionVec[1] ? static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG) : 0; 46 } 47 } 48 label_ = i32Flag; 49 #if !defined(__ARKUI_CROSS__) 50 SetHwIcuDirectory(); 51 #endif 52 bool fatal = (i32Flag & static_cast<uint32_t>(ConverterFlags::FATAL_FLG)) == 53 static_cast<uint32_t>(ConverterFlags::FATAL_FLG); 54 UErrorCode codeflag = U_ZERO_ERROR; 55 UConverter *conv = CreateConverter(encStr_, codeflag); 56 57 if (U_FAILURE(codeflag)) { 58 HILOG_ERROR("ucnv_open failed !"); 59 return; 60 } 61 if (fatal) { 62 codeflag = U_ZERO_ERROR; 63 ucnv_setToUCallBack(conv, UCNV_TO_U_CALLBACK_STOP, nullptr, nullptr, nullptr, &codeflag); 64 } 65 TransformToolPointer tempTranTool(conv, ConverterClose); 66 tranTool_ = std::move(tempTranTool); 67 } 68 Decode(napi_env env,napi_value src,bool iflag)69 napi_value TextDecoder::Decode(napi_env env, napi_value src, bool iflag) 70 { 71 uint8_t flags = 0; 72 flags |= (iflag ? 0 : static_cast<uint8_t>(ConverterFlags::FLUSH_FLG)); 73 UBool flush = ((flags & static_cast<uint8_t>(ConverterFlags::FLUSH_FLG))) == 74 static_cast<uint8_t>(ConverterFlags::FLUSH_FLG); 75 napi_typedarray_type type; 76 size_t length = 0; 77 void *data1 = nullptr; 78 size_t byteOffset = 0; 79 napi_value arrayBuffer = nullptr; 80 NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &data1, &arrayBuffer, &byteOffset)); 81 const char *source = static_cast<char*>(data1); 82 size_t limit = GetMinByteSize() * length; 83 size_t len = limit * sizeof(UChar); 84 UChar *arr = nullptr; 85 if (limit > 0) { 86 arr = new UChar[limit + 1]; 87 if (memset_s(arr, len + sizeof(UChar), 0, len + sizeof(UChar)) != EOK) { 88 HILOG_ERROR("decode arr memset_s failed"); 89 FreedMemory(arr); 90 return nullptr; 91 } 92 } else { 93 HILOG_DEBUG("limit is error"); 94 return nullptr; 95 } 96 UChar *target = arr; 97 size_t tarStartPos = reinterpret_cast<uintptr_t>(arr); 98 UErrorCode codeFlag = U_ZERO_ERROR; 99 ucnv_toUnicode(GetConverterPtr(), &target, target + len, &source, source + length, nullptr, flush, &codeFlag); 100 if (codeFlag != U_ZERO_ERROR) { 101 return ThrowError(env, "TextDecoder decoding error."); 102 } 103 104 size_t resultLength = 0; 105 bool omitInitialBom = false; 106 DecodeArr decArr(target, tarStartPos, limit); 107 SetBomFlag(arr, codeFlag, decArr, resultLength, omitInitialBom); 108 UChar *arrDat = arr; 109 if (omitInitialBom && resultLength > 0) { 110 arrDat = &arr[2]; // 2: Obtains the 2 value of the array. 111 } 112 std::string tepStr = ConvertToString(arrDat, length); 113 napi_value resultStr = nullptr; 114 NAPI_CALL(env, napi_create_string_utf8(env, tepStr.c_str(), tepStr.size(), &resultStr)); 115 FreedMemory(arr); 116 if (flush) { 117 label_ &= static_cast<uint32_t>(ConverterFlags::BOM_SEEN_FLG); 118 Reset(); 119 } 120 return resultStr; 121 } 122 GetEncoding(napi_env env) const123 napi_value TextDecoder::GetEncoding(napi_env env) const 124 { 125 size_t length = strlen(encStr_.c_str()); 126 napi_value result = nullptr; 127 NAPI_CALL(env, napi_create_string_utf8(env, encStr_.c_str(), length, &result)); 128 return result; 129 } 130 GetFatal(napi_env env) const131 napi_value TextDecoder::GetFatal(napi_env env) const 132 { 133 uint32_t temp = label_ & static_cast<uint32_t>(ConverterFlags::FATAL_FLG); 134 bool comRst = false; 135 if (temp == static_cast<uint32_t>(ConverterFlags::FATAL_FLG)) { 136 comRst = true; 137 } else { 138 comRst = false; 139 } 140 napi_value result = nullptr; 141 NAPI_CALL(env, napi_get_boolean(env, comRst, &result)); 142 return result; 143 } 144 GetIgnoreBOM(napi_env env) const145 napi_value TextDecoder::GetIgnoreBOM(napi_env env) const 146 { 147 uint32_t temp = label_ & static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG); 148 bool comRst = false; 149 if (temp == static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG)) { 150 comRst = true; 151 } else { 152 comRst = false; 153 } 154 napi_value result; 155 NAPI_CALL(env, napi_get_boolean(env, comRst, &result)); 156 return result; 157 } 158 GetMinByteSize() const159 size_t TextDecoder::GetMinByteSize() const 160 { 161 if (tranTool_ == nullptr) { 162 return 0; 163 } 164 size_t res = static_cast<size_t>(ucnv_getMinCharSize(tranTool_.get())); 165 return res; 166 } 167 Reset() const168 void TextDecoder::Reset() const 169 { 170 if (tranTool_ == nullptr) { 171 return; 172 } 173 ucnv_reset(tranTool_.get()); 174 } 175 FreedMemory(UChar * pData)176 void TextDecoder::FreedMemory(UChar *pData) 177 { 178 if (pData != nullptr) { 179 delete[] pData; 180 pData = nullptr; 181 } 182 } 183 SetBomFlag(const UChar * arr,const UErrorCode codeFlag,const DecodeArr decArr,size_t & rstLen,bool & bomFlag)184 void TextDecoder::SetBomFlag(const UChar *arr, const UErrorCode codeFlag, const DecodeArr decArr, 185 size_t &rstLen, bool &bomFlag) 186 { 187 if (arr == nullptr) { 188 return; 189 } 190 if (U_SUCCESS(codeFlag)) { 191 if (decArr.limitLen > 0) { 192 rstLen = reinterpret_cast<uintptr_t>(decArr.target) - decArr.tarStartPos; 193 if (rstLen > 0 && IsUnicode() && !IsIgnoreBom() && !IsBomFlag()) { 194 bomFlag = (arr[0] == 0xFEFF) ? true : false; 195 label_ |= static_cast<uint32_t>(ConverterFlags::BOM_SEEN_FLG); 196 } 197 } 198 } 199 } 200 ThrowError(napi_env env,const char * errMessage)201 napi_value TextDecoder::ThrowError(napi_env env, const char* errMessage) 202 { 203 napi_value utilError = nullptr; 204 napi_value code = nullptr; 205 uint32_t errCode = 10200019; 206 napi_create_uint32(env, errCode, &code); 207 napi_value name = nullptr; 208 std::string errName = "BusinessError"; 209 napi_value msg = nullptr; 210 napi_create_string_utf8(env, errMessage, NAPI_AUTO_LENGTH, &msg); 211 napi_create_string_utf8(env, errName.c_str(), NAPI_AUTO_LENGTH, &name); 212 napi_create_error(env, nullptr, msg, &utilError); 213 napi_set_named_property(env, utilError, "code", code); 214 napi_set_named_property(env, utilError, "name", name); 215 napi_throw(env, utilError); 216 napi_value res = nullptr; 217 NAPI_CALL(env, napi_get_undefined(env, &res)); 218 return res; 219 } 220 } 221