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