1 /*
2  * Copyright (C) 2021-2023 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 "napi_util.h"
17 #include <codecvt>
18 #include <cstdio>
19 #include <locale>
20 #include <string>
21 
22 #include "hilog_wrapper.h"
23 #include "securec.h"
24 #include "usb_common.h"
25 #include "usb_errors.h"
26 #include "usb_napi_errors.h"
27 namespace OHOS {
28 namespace USB {
29 const int32_t MAX_STR_LENGTH = 1024;
JsValueToString(const napi_env & env,const napi_value & value,const int32_t bufLen,std::string & target)30 void NapiUtil::JsValueToString(const napi_env &env, const napi_value &value, const int32_t bufLen, std::string &target)
31 {
32     if (bufLen <= 0 || bufLen > MAX_STR_LENGTH) {
33         USB_HILOGE(MODULE_JS_NAPI, "string too long malloc failed");
34         return;
35     }
36     // 1 represent '\0'
37     int32_t actBufLen = bufLen + 1;
38     std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBufLen);
39 
40     errno_t ret = memset_s(buf.get(), actBufLen, 0, actBufLen);
41     RETURN_IF_WITH_LOG(ret != EOK, "JsValueToString memset_s failed.");
42 
43     size_t result = 0;
44     napi_get_value_string_utf8(env, value, buf.get(), actBufLen, &result);
45     target = buf.get();
46 }
47 
JsObjectToString(const napi_env & env,const napi_value & object,std::string fieldStr,const int32_t bufLen,std::string & fieldRef)48 void NapiUtil::JsObjectToString(
49     const napi_env &env, const napi_value &object, std::string fieldStr, const int32_t bufLen, std::string &fieldRef)
50 {
51     if (bufLen <= 0) {
52         USB_HILOGE(MODULE_JS_NAPI, "invalid bufLen=%{public}d", bufLen);
53         return;
54     }
55 
56     bool hasProperty = false;
57     napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
58     if (hasProperty) {
59         napi_value field;
60         napi_valuetype valueType;
61 
62         napi_get_named_property(env, object, fieldStr.c_str(), &field);
63         napi_typeof(env, field, &valueType);
64         USB_ASSERT_RETURN_VOID(
65             env, valueType == napi_string, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be string.");
66         // 1 represent '\0'
67         int32_t actBufLen = bufLen + 1;
68         std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBufLen);
69 
70         errno_t ret = memset_s(buf.get(), actBufLen, 0, actBufLen);
71         RETURN_IF_WITH_LOG(ret != EOK, "JsObjectToString memset_s failed.");
72 
73         size_t result = 0;
74         napi_get_value_string_utf8(env, field, buf.get(), actBufLen, &result);
75         fieldRef = buf.get();
76     } else {
77         USB_HILOGW(MODULE_JS_NAPI, "js to str no property: %{public}s", fieldStr.c_str());
78     }
79 }
80 
JsObjectGetProperty(const napi_env & env,const napi_value & object,std::string fieldStr,napi_value & value)81 bool NapiUtil::JsObjectGetProperty(
82     const napi_env &env, const napi_value &object, std::string fieldStr, napi_value &value)
83 {
84     bool hasProperty = false;
85     napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
86     if (hasProperty) {
87         napi_get_named_property(env, object, fieldStr.c_str(), &value);
88     } else {
89         USB_HILOGW(MODULE_JS_NAPI, "js object has no property: %{public}s", fieldStr.c_str());
90     }
91     return hasProperty;
92 }
93 
JsObjectToBool(const napi_env & env,const napi_value & object,std::string fieldStr,bool & fieldRef)94 void NapiUtil::JsObjectToBool(const napi_env &env, const napi_value &object, std::string fieldStr, bool &fieldRef)
95 {
96     bool hasProperty = false;
97     napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
98     if (hasProperty) {
99         napi_value field;
100         napi_valuetype valueType;
101 
102         napi_get_named_property(env, object, fieldStr.c_str(), &field);
103         napi_typeof(env, field, &valueType);
104         USB_ASSERT_RETURN_VOID(
105             env, valueType == napi_boolean, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be boolean.");
106         napi_get_value_bool(env, field, &fieldRef);
107     } else {
108         USB_HILOGW(MODULE_JS_NAPI, "js to boolean no property: %{public}s", fieldStr.c_str());
109     }
110 }
111 
JsObjectToInt(const napi_env & env,const napi_value & object,std::string fieldStr,int32_t & fieldRef)112 void NapiUtil::JsObjectToInt(const napi_env &env, const napi_value &object, std::string fieldStr, int32_t &fieldRef)
113 {
114     bool hasProperty = false;
115     napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
116     if (hasProperty) {
117         napi_value field;
118         napi_valuetype valueType;
119 
120         napi_get_named_property(env, object, fieldStr.c_str(), &field);
121         napi_typeof(env, field, &valueType);
122         USB_ASSERT_RETURN_VOID(
123             env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
124         napi_get_value_int32(env, field, &fieldRef);
125     } else {
126         USB_HILOGW(MODULE_JS_NAPI, "js to int32_t no property: %{public}s", fieldStr.c_str());
127     }
128 }
129 
JsObjectToUint(const napi_env & env,const napi_value & object,const std::string & fieldStr,uint32_t & fieldRef)130 void NapiUtil::JsObjectToUint(
131     const napi_env &env, const napi_value &object, const std::string &fieldStr, uint32_t &fieldRef)
132 {
133     bool hasProperty = false;
134     napi_status status = napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
135     if (status != napi_ok || !hasProperty) {
136         USB_HILOGE(MODULE_JS_NAPI, "js to uint32_t no property: %{public}s", fieldStr.c_str());
137         return;
138     }
139 
140     napi_value field = nullptr;
141     napi_valuetype valueType;
142 
143     status = napi_get_named_property(env, object, fieldStr.c_str(), &field);
144     if (status != napi_ok) {
145         USB_HILOGE(MODULE_JS_NAPI, "get property failed: %{public}s", fieldStr.c_str());
146         return;
147     }
148 
149     status = napi_typeof(env, field, &valueType);
150     if (status != napi_ok) {
151         USB_HILOGE(MODULE_JS_NAPI, "type error failed: %{public}s", fieldStr.c_str());
152         return;
153     }
154 
155     USB_ASSERT_RETURN_VOID(
156         env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
157     status = napi_get_value_uint32(env, field, &fieldRef);
158     if (status != napi_ok) {
159         USB_HILOGE(MODULE_JS_NAPI, "get value failed: %{public}s", fieldStr.c_str());
160     }
161 }
162 
JsUint8ArrayParse(const napi_env & env,const napi_value & object,uint8_t ** uint8Buffer,size_t & bufferSize,size_t & offset)163 bool NapiUtil::JsUint8ArrayParse(
164     const napi_env &env, const napi_value &object, uint8_t **uint8Buffer, size_t &bufferSize, size_t &offset)
165 {
166     bool isTypedArray = false;
167     if (napi_is_typedarray(env, object, &isTypedArray) != napi_ok || !isTypedArray) {
168         USB_ASSERT_RETURN_FALSE(env, isTypedArray, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be TypedArray.");
169         USB_HILOGW(MODULE_JS_NAPI, "invalid type");
170         return false;
171     }
172 
173     napi_typedarray_type type;
174     napi_value buffer;
175 
176     napi_status infoStatus = napi_get_typedarray_info(
177         env, object, &type, &bufferSize, reinterpret_cast<void **>(uint8Buffer), &buffer, &offset);
178     if (infoStatus != napi_ok) {
179         USB_HILOGW(MODULE_JS_NAPI, "get typedarray info failed, status: %{public}d", infoStatus);
180         return false;
181     }
182     USB_ASSERT_RETURN_FALSE(
183         env, type == napi_uint8_array, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be Uint8Array.");
184     USB_ASSERT_RETURN_FALSE(
185         env, bufferSize != 0, OHEC_COMMON_PARAM_ERROR, "The size of buffer must be a positive number.");
186     return true;
187 }
188 
Uint8ArrayToJsValue(const napi_env & env,std::vector<uint8_t> & uint8Buffer,size_t bufferSize,napi_value & result)189 void NapiUtil::Uint8ArrayToJsValue(
190     const napi_env &env, std::vector<uint8_t> &uint8Buffer, size_t bufferSize, napi_value &result)
191 {
192     uint8_t *nativeArraybuffer = nullptr;
193     napi_value nativeValue = nullptr;
194     napi_create_arraybuffer(env, bufferSize, reinterpret_cast<void **>(&nativeArraybuffer), &nativeValue);
195 
196     errno_t ret = memcpy_s(nativeArraybuffer, bufferSize, uint8Buffer.data(), bufferSize);
197     if (ret != EOK) {
198         USB_HILOGE(MODULE_JS_NAPI, "memcpy_s failed");
199         return;
200     }
201 
202     napi_create_typedarray(env, napi_uint8_array, bufferSize, nativeValue, 0, &result);
203 }
204 
SetValueUtf8String(const napi_env & env,std::string fieldStr,std::string str,napi_value & result)205 void NapiUtil::SetValueUtf8String(const napi_env &env, std::string fieldStr, std::string str, napi_value &result)
206 {
207     napi_value value;
208     napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &value);
209     napi_set_named_property(env, result, fieldStr.c_str(), value);
210 }
211 
SetValueInt32(const napi_env & env,std::string fieldStr,const int32_t intValue,napi_value & result)212 void NapiUtil::SetValueInt32(const napi_env &env, std::string fieldStr, const int32_t intValue, napi_value &result)
213 {
214     napi_value value;
215     napi_create_int32(env, intValue, &value);
216     napi_set_named_property(env, result, fieldStr.c_str(), value);
217 }
218 
SetValueUint32(const napi_env & env,const std::string & fieldStr,const uint32_t uintValue,napi_value & result)219 void NapiUtil::SetValueUint32(
220     const napi_env &env, const std::string &fieldStr, const uint32_t uintValue, napi_value &result)
221 {
222     napi_value value = nullptr;
223     napi_status status = napi_create_uint32(env, uintValue, &value);
224     if (status != napi_ok) {
225         USB_HILOGE(MODULE_JS_NAPI, "create uint32 failed:%{public}s", fieldStr.c_str());
226         return;
227     }
228 
229     status = napi_set_named_property(env, result, fieldStr.c_str(), value);
230     if (status != napi_ok) {
231         USB_HILOGE(MODULE_JS_NAPI, "set property failed:%{public}s", fieldStr.c_str());
232     }
233 }
234 
SetValueBool(const napi_env & env,std::string fieldStr,const bool boolValue,napi_value & result)235 void NapiUtil::SetValueBool(const napi_env &env, std::string fieldStr, const bool boolValue, napi_value &result)
236 {
237     napi_value value;
238     napi_get_boolean(env, boolValue, &value);
239     napi_set_named_property(env, result, fieldStr.c_str(), value);
240 }
241 
242 } // namespace USB
243 } // namespace OHOS
244