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 "napi_scan_utils.h"
17
18 #include <fcntl.h>
19 #include "ability.h"
20 #include "napi_base_context.h"
21 #include "scan_log.h"
22 #include "scan_util.h"
23 #include "securec.h"
24
25 namespace OHOS::Scan {
26 static constexpr const int MAX_STRING_LENGTH = 65536;
27 const std::string GLOBAL_ID_DELIMITER = ":";
28 const std::string EXTENSION_CID_DELIMITER = ":";
29 const std::string TASK_EVENT_DELIMITER = "-";
30
GetValueType(napi_env env,napi_value value)31 napi_valuetype NapiScanUtils::GetValueType(napi_env env, napi_value value)
32 {
33 if (value == nullptr) {
34 return napi_undefined;
35 }
36
37 napi_valuetype valueType = napi_undefined;
38 SCAN_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
39 return valueType;
40 }
41
42 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)43 bool NapiScanUtils::HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
44 {
45 bool hasProperty = false;
46 SCAN_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
47 return hasProperty;
48 }
49
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)50 napi_value NapiScanUtils::GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
51 {
52 napi_value value = nullptr;
53 bool hasProperty = false;
54 SCAN_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
55 if (!hasProperty) {
56 return value;
57 }
58 SCAN_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
59 return value;
60 }
61
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)62 void NapiScanUtils::SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
63 {
64 (void)napi_set_named_property(env, object, name.c_str(), value);
65 }
66
GetPropertyNames(napi_env env,napi_value object)67 std::vector<std::string> NapiScanUtils::GetPropertyNames(napi_env env, napi_value object)
68 {
69 std::vector<std::string> ret;
70 napi_value names = nullptr;
71 SCAN_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
72 uint32_t length = 0;
73 SCAN_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
74 for (uint32_t index = 0; index < length; ++index) {
75 napi_value name = nullptr;
76 if (napi_get_element(env, names, index, &name) != napi_ok) {
77 continue;
78 }
79 if (GetValueType(env, name) != napi_string) {
80 continue;
81 }
82 ret.emplace_back(GetStringFromValueUtf8(env, name));
83 }
84 return ret;
85 }
86
87 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)88 napi_value NapiScanUtils::CreateUint32(napi_env env, uint32_t code)
89 {
90 napi_value value = nullptr;
91 if (napi_create_uint32(env, code, &value) != napi_ok) {
92 return nullptr;
93 }
94 return value;
95 }
96
GetUint32FromValue(napi_env env,napi_value value)97 uint32_t NapiScanUtils::GetUint32FromValue(napi_env env, napi_value value)
98 {
99 uint32_t ret = 0;
100 SCAN_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
101 return ret;
102 }
103
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)104 uint32_t NapiScanUtils::GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
105 {
106 if (!HasNamedProperty(env, object, propertyName)) {
107 return 0;
108 }
109 napi_value value = GetNamedProperty(env, object, propertyName);
110 return GetUint32FromValue(env, value);
111 }
112
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)113 void NapiScanUtils::SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
114 {
115 napi_value jsValue = CreateUint32(env, value);
116 if (GetValueType(env, jsValue) != napi_number) {
117 return;
118 }
119
120 napi_set_named_property(env, object, name.c_str(), jsValue);
121 }
122
123 /* INT32 */
CreateInt32(napi_env env,int32_t code)124 napi_value NapiScanUtils::CreateInt32(napi_env env, int32_t code)
125 {
126 napi_value value = nullptr;
127 if (napi_create_int32(env, code, &value) != napi_ok) {
128 return nullptr;
129 }
130 return value;
131 }
132
GetInt32FromValue(napi_env env,napi_value value)133 int32_t NapiScanUtils::GetInt32FromValue(napi_env env, napi_value value)
134 {
135 int32_t ret = 0;
136 SCAN_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
137 return ret;
138 }
139
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)140 int32_t NapiScanUtils::GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
141 {
142 if (!HasNamedProperty(env, object, propertyName)) {
143 return 0;
144 }
145 napi_value value = GetNamedProperty(env, object, propertyName);
146 return GetInt32FromValue(env, value);
147 }
148
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)149 void NapiScanUtils::SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
150 {
151 napi_value jsValue = CreateInt32(env, value);
152 if (GetValueType(env, jsValue) != napi_number) {
153 return;
154 }
155
156 napi_set_named_property(env, object, name.c_str(), jsValue);
157 }
158
159 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)160 napi_value NapiScanUtils::CreateStringUtf8(napi_env env, const std::string &str)
161 {
162 napi_value value = nullptr;
163 if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
164 return nullptr;
165 }
166 return value;
167 }
168
GetStringFromValueUtf8(napi_env env,napi_value value)169 std::string NapiScanUtils::GetStringFromValueUtf8(napi_env env, napi_value value)
170 {
171 std::string result;
172 std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
173 size_t length = 0;
174 SCAN_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
175 if (length > 0) {
176 return result.append(&str[0], length);
177 }
178 return result;
179 }
180
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)181 std::string NapiScanUtils::GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
182 {
183 if (!HasNamedProperty(env, object, propertyName)) {
184 return "";
185 }
186 napi_value value = GetNamedProperty(env, object, propertyName);
187 return GetStringFromValueUtf8(env, value);
188 }
189
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)190 void NapiScanUtils::SetStringPropertyUtf8(
191 napi_env env, napi_value object, const std::string &name, const std::string &value)
192 {
193 napi_value jsValue = CreateStringUtf8(env, value);
194 if (GetValueType(env, jsValue) != napi_string) {
195 return;
196 }
197 napi_set_named_property(env, object, name.c_str(), jsValue);
198 }
199
200 /* array buffer */
201
CreateArrayBuffer(napi_env env,size_t length,void ** data)202 napi_value NapiScanUtils::CreateArrayBuffer(napi_env env, size_t length, void **data)
203 {
204 napi_value object = nullptr;
205 SCAN_CALL(env, napi_create_arraybuffer(env, length, data, &object));
206 return object;
207 }
208
ValueIsArrayBuffer(napi_env env,napi_value value)209 bool NapiScanUtils::ValueIsArrayBuffer(napi_env env, napi_value value)
210 {
211 bool isArrayBuffer = false;
212 SCAN_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
213 return isArrayBuffer;
214 }
215
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)216 void *NapiScanUtils::GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
217 {
218 if (length == nullptr) {
219 return nullptr;
220 }
221
222 void *data = nullptr;
223 SCAN_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
224 return data;
225 }
226
227 /* object */
CreateObject(napi_env env)228 napi_value NapiScanUtils::CreateObject(napi_env env)
229 {
230 napi_value object = nullptr;
231 SCAN_CALL(env, napi_create_object(env, &object));
232 return object;
233 }
234
235 /* undefined */
GetUndefined(napi_env env)236 napi_value NapiScanUtils::GetUndefined(napi_env env)
237 {
238 napi_value undefined = nullptr;
239 SCAN_CALL(env, napi_get_undefined(env, &undefined));
240 return undefined;
241 }
242
243 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)244 napi_value NapiScanUtils::CallFunction(
245 napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
246 {
247 napi_value res = nullptr;
248 SCAN_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
249 return res;
250 }
251
252 /* reference */
CreateReference(napi_env env,napi_value callback)253 napi_ref NapiScanUtils::CreateReference(napi_env env, napi_value callback)
254 {
255 napi_ref callbackRef = nullptr;
256 SCAN_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
257 return callbackRef;
258 }
259
GetReference(napi_env env,napi_ref callbackRef)260 napi_value NapiScanUtils::GetReference(napi_env env, napi_ref callbackRef)
261 {
262 napi_value callback = nullptr;
263 SCAN_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
264 return callback;
265 }
266
DeleteReference(napi_env env,napi_ref callbackRef)267 void NapiScanUtils::DeleteReference(napi_env env, napi_ref callbackRef)
268 {
269 if (env != nullptr && callbackRef != nullptr) {
270 (void)napi_delete_reference(env, callbackRef);
271 }
272 }
273
274 /* boolean */
CreateBoolean(napi_env env,bool value)275 napi_value NapiScanUtils::CreateBoolean(napi_env env, bool value)
276 {
277 napi_value jsValue = nullptr;
278 if (napi_get_boolean(env, value, &jsValue) != napi_ok) {
279 return nullptr;
280 }
281 return jsValue;
282 }
283
GetBooleanFromValue(napi_env env,napi_value value)284 bool NapiScanUtils::GetBooleanFromValue(napi_env env, napi_value value)
285 {
286 bool ret = false;
287 SCAN_CALL_BASE(env, napi_get_value_bool(env, value, &ret), 0);
288 return ret;
289 }
290
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)291 bool NapiScanUtils::GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
292 {
293 if (!HasNamedProperty(env, object, propertyName)) {
294 return false;
295 }
296 napi_value value = GetNamedProperty(env, object, propertyName);
297 bool ret = false;
298 SCAN_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
299 return ret;
300 }
301
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)302 void NapiScanUtils::SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
303 {
304 napi_value jsValue = nullptr;
305 SCAN_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
306 if (GetValueType(env, jsValue) != napi_boolean) {
307 return;
308 }
309
310 napi_set_named_property(env, object, name.c_str(), jsValue);
311 }
312
313 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)314 void NapiScanUtils::DefineProperties(
315 napi_env env, napi_value object, const std::initializer_list<napi_property_descriptor> &properties)
316 {
317 napi_property_descriptor descriptors[properties.size()];
318 std::copy(properties.begin(), properties.end(), descriptors);
319
320 (void)napi_define_properties(env, object, properties.size(), descriptors);
321 }
322
ToLower(const std::string & s)323 std::string NapiScanUtils::ToLower(const std::string &s)
324 {
325 std::string res = s;
326 std::transform(res.begin(), res.end(), res.begin(), tolower);
327 return res;
328 }
329
GetValueString(napi_env env,napi_value value)330 std::string NapiScanUtils::GetValueString(napi_env env, napi_value value)
331 {
332 std::string resultValue = "";
333 char value_string[256] = { 0 };
334 size_t value_size = 256;
335 size_t result = 0;
336 napi_status status = napi_get_value_string_utf8(env, value, value_string, value_size, &result);
337 if (status == napi_ok && result > 0) {
338 resultValue = value_string;
339 }
340 return resultValue;
341 }
342
GetExtensionId(const std::string & globalId)343 std::string NapiScanUtils::GetExtensionId(const std::string &globalId)
344 {
345 auto pos = globalId.find(GLOBAL_ID_DELIMITER);
346 if (pos == std::string::npos) {
347 return "";
348 }
349 return globalId.substr(0, pos);
350 }
351
GetGlobalId(const std::string & extensionId,const std::string & localId)352 std::string NapiScanUtils::GetGlobalId(const std::string& extensionId, const std::string& localId)
353 {
354 return extensionId + GLOBAL_ID_DELIMITER + localId;
355 }
356
GetLocalId(const std::string & globalId,const std::string & extensionId)357 std::string NapiScanUtils::GetLocalId(const std::string& globalId, const std::string& extensionId)
358 {
359 auto pos = globalId.find(GLOBAL_ID_DELIMITER);
360 if (pos == std::string::npos) {
361 return "";
362 }
363
364 if (globalId.substr(0, pos) != extensionId) {
365 return "";
366 }
367 return globalId.substr(pos + 1);
368 }
369
EncodeExtensionCid(const std::string & extensionId,uint32_t callbackId)370 std::string NapiScanUtils::EncodeExtensionCid(const std::string &extensionId, uint32_t callbackId)
371 {
372 return extensionId + EXTENSION_CID_DELIMITER + std::to_string(callbackId);
373 }
374
DecodeExtensionCid(const std::string & cid,std::string & extensionId,uint32_t & callbackId)375 bool NapiScanUtils::DecodeExtensionCid(const std::string &cid, std::string &extensionId, uint32_t &callbackId)
376 {
377 auto pos = cid.find(EXTENSION_CID_DELIMITER);
378 if (pos == std::string::npos) {
379 return false;
380 }
381 extensionId = cid.substr(0, pos);
382 int32_t callbackIdTmp = 0;
383 if (!ScanUtil::ConvertToInt(cid.substr(pos + 1), callbackIdTmp)) {
384 return false;
385 }
386 callbackId = static_cast<uint32_t>(callbackIdTmp);
387 return true;
388 }
389
GetTaskEventId(const std::string & taskId,const std::string & type)390 std::string NapiScanUtils::GetTaskEventId(const std::string &taskId, const std::string &type)
391 {
392 return type + TASK_EVENT_DELIMITER + taskId;
393 }
394
OpenFile(const std::string & filePath)395 int32_t NapiScanUtils::OpenFile(const std::string &filePath)
396 {
397 if (!IsPathValid(filePath)) {
398 return SCAN_INVALID_ID;
399 }
400 int32_t fd = open(filePath.c_str(), O_RDONLY);
401 SCAN_HILOGD("fd: %{public}d", fd);
402 if (fd < 0) {
403 SCAN_HILOGE("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
404 return SCAN_INVALID_ID;
405 }
406 return fd;
407 }
408
IsPathValid(const std::string & filePath)409 bool NapiScanUtils::IsPathValid(const std::string &filePath)
410 {
411 auto path = filePath.substr(0, filePath.rfind('/'));
412 char resolvedPath[PATH_MAX + 1] = { 0 };
413 if (path.length() > PATH_MAX || realpath(path.c_str(), resolvedPath) == nullptr ||
414 strncmp(resolvedPath, path.c_str(), path.length()) != 0) {
415 SCAN_HILOGE("invalid file path!");
416 return false;
417 }
418 return true;
419 }
420
GetIdFromFdPath(const std::string & fdPath)421 uint32_t NapiScanUtils::GetIdFromFdPath(const std::string &fdPath)
422 {
423 std::string fd_str = fdPath.substr(fdPath.rfind('/') + 1, fdPath.length());
424 std::stringstream getStrStream(fd_str);
425 uint32_t fd = 0;
426 if (!(getStrStream >> fd)) {
427 SCAN_HILOGD("failed to convert to uint32");
428 }
429 return fd;
430 }
431
GetJsVal(napi_env env,napi_callback_info info,napi_value argv[],size_t length)432 size_t NapiScanUtils::GetJsVal(napi_env env, napi_callback_info info, napi_value argv[], size_t length)
433 {
434 size_t argc = length;
435 napi_value thisVal = nullptr;
436 void *data = nullptr;
437 napi_get_cb_info(env, info, &argc, argv, &thisVal, &data);
438 return argc;
439 }
440
441 } // namespace OHOS::Scan
442