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