• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "accesstoken_kit.h"
24 #include "tokenid_kit.h"
25 
26 namespace OHOS::Scan {
27 static constexpr const int MAX_STRING_LENGTH = 65536;
28 const std::string GLOBAL_ID_DELIMITER = ":";
29 const std::string EXTENSION_CID_DELIMITER = ":";
30 const std::string TASK_EVENT_DELIMITER = "-";
31 std::unordered_map<uint32_t, std::string> NapiScanUtils::scanErrorCodeMap_ = {
32     {E_SCAN_NO_PERMISSION, "SCAN_ERROR_NO_PERMISSION", },
33     {E_SCAN_ERROR_NOT_SYSTEM_APPLICATION, "SCAN_ERROR_NOT_SYSTEM_APPLICATION", },
34     {E_SCAN_INVALID_PARAMETER, "SCAN_ERROR_INVALID_PARAMETER"},
35     {E_SCAN_GENERIC_FAILURE, "SCAN_ERROR_GENERIC_FAILURE"},
36     {E_SCAN_RPC_FAILURE, "SCAN_ERROR_RPC_FAILURE"},
37     {E_SCAN_SERVER_FAILURE, "SCAN_ERROR_SERVER_FAILURE"},
38     {E_SCAN_UNSUPPORTED, "SCAN_ERROR_UNSUPPORTED"},
39     {E_SCAN_CANCELLED, "SCAN_ERROR_CANCELED"},
40     {E_SCAN_DEVICE_BUSY, "SCAN_ERROR_DEVICE_BUSY"},
41     {E_SCAN_INVAL, "SCAN_ERROR_INVALID"},
42     {E_SCAN_JAMMED, "SCAN_ERROR_JAMMED"},
43     {E_SCAN_NO_DOCS, "SCAN_ERROR_NO_DOCS"},
44     {E_SCAN_COVER_OPEN, "SCAN_ERROR_COVER_OPEN"},
45     {E_SCAN_IO_ERROR, "SCAN_ERROR_IO_ERROR"},
46     {E_SCAN_NO_MEM, "SCAN_ERROR_NO_MEMORY"},
47 };
GetValueType(napi_env env,napi_value value)48 napi_valuetype NapiScanUtils::GetValueType(napi_env env, napi_value value)
49 {
50     if (value == nullptr) {
51         return napi_undefined;
52     }
53 
54     napi_valuetype valueType = napi_undefined;
55     SCAN_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
56     return valueType;
57 }
58 
59 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)60 bool NapiScanUtils::HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
61 {
62     if (object == nullptr) {
63         return false;
64     }
65     bool hasProperty = false;
66     SCAN_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
67     return hasProperty;
68 }
69 
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)70 napi_value NapiScanUtils::GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
71 {
72     if (object == nullptr) {
73         return nullptr;
74     }
75     napi_value value = nullptr;
76     bool hasProperty = false;
77     SCAN_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
78     if (!hasProperty) {
79         return value;
80     }
81     SCAN_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
82     return value;
83 }
84 
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)85 void NapiScanUtils::SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
86 {
87     if (object == nullptr) {
88         return;
89     }
90     (void)napi_set_named_property(env, object, name.c_str(), value);
91 }
92 
GetPropertyNames(napi_env env,napi_value object)93 std::vector<std::string> NapiScanUtils::GetPropertyNames(napi_env env, napi_value object)
94 {
95     std::vector<std::string> ret;
96     if (object == nullptr) {
97         return ret;
98     }
99     napi_value names = nullptr;
100     SCAN_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
101     uint32_t length = 0;
102     SCAN_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
103     for (uint32_t index = 0; index < length; ++index) {
104         napi_value name = nullptr;
105         if (napi_get_element(env, names, index, &name) != napi_ok) {
106             continue;
107         }
108         if (GetValueType(env, name) != napi_string) {
109             continue;
110         }
111         ret.emplace_back(GetStringFromValueUtf8(env, name));
112     }
113     return ret;
114 }
115 
116 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)117 napi_value NapiScanUtils::CreateUint32(napi_env env, uint32_t code)
118 {
119     napi_value value = nullptr;
120     if (napi_create_uint32(env, code, &value) != napi_ok) {
121         return nullptr;
122     }
123     return value;
124 }
125 
GetUint32FromValue(napi_env env,napi_value value)126 uint32_t NapiScanUtils::GetUint32FromValue(napi_env env, napi_value value)
127 {
128     if (value == nullptr) {
129         return 0;
130     }
131     uint32_t ret = 0;
132     SCAN_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
133     return ret;
134 }
135 
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)136 uint32_t NapiScanUtils::GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
137 {
138     if (object == nullptr) {
139         return 0;
140     }
141     if (!HasNamedProperty(env, object, propertyName)) {
142         return 0;
143     }
144     napi_value value = GetNamedProperty(env, object, propertyName);
145     return GetUint32FromValue(env, value);
146 }
147 
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)148 void NapiScanUtils::SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
149 {
150     if (object == nullptr) {
151         return;
152     }
153     napi_value jsValue = CreateUint32(env, value);
154     if (GetValueType(env, jsValue) != napi_number) {
155         return;
156     }
157 
158     napi_set_named_property(env, object, name.c_str(), jsValue);
159 }
160 
161 /* INT32 */
CreateInt32(napi_env env,int32_t code)162 napi_value NapiScanUtils::CreateInt32(napi_env env, int32_t code)
163 {
164     napi_value value = nullptr;
165     if (napi_create_int32(env, code, &value) != napi_ok) {
166         return nullptr;
167     }
168     return value;
169 }
170 
GetInt32FromValue(napi_env env,napi_value value)171 int32_t NapiScanUtils::GetInt32FromValue(napi_env env, napi_value value)
172 {
173     if (value == nullptr) {
174         return 0;
175     }
176     int32_t ret = 0;
177     SCAN_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
178     return ret;
179 }
180 
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)181 int32_t NapiScanUtils::GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
182 {
183     if (object == nullptr) {
184         return 0;
185     }
186     if (!HasNamedProperty(env, object, propertyName)) {
187         return 0;
188     }
189     napi_value value = GetNamedProperty(env, object, propertyName);
190     return GetInt32FromValue(env, value);
191 }
192 
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)193 void NapiScanUtils::SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
194 {
195     if (object == nullptr) {
196         return;
197     }
198     napi_value jsValue = CreateInt32(env, value);
199     if (GetValueType(env, jsValue) != napi_number) {
200         return;
201     }
202 
203     napi_set_named_property(env, object, name.c_str(), jsValue);
204 }
205 
206 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)207 napi_value NapiScanUtils::CreateStringUtf8(napi_env env, const std::string &str)
208 {
209     napi_value value = nullptr;
210     if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
211         return nullptr;
212     }
213     return value;
214 }
215 
GetStringFromValueUtf8(napi_env env,napi_value value)216 std::string NapiScanUtils::GetStringFromValueUtf8(napi_env env, napi_value value)
217 {
218     if (value == nullptr) {
219         return "";
220     }
221     std::string result;
222     std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
223     size_t length = 0;
224     SCAN_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
225     if (length > 0) {
226         return result.append(&str[0], length);
227     }
228     return result;
229 }
230 
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)231 std::string NapiScanUtils::GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
232 {
233     if (object == nullptr) {
234         return "";
235     }
236     if (!HasNamedProperty(env, object, propertyName)) {
237         return "";
238     }
239     napi_value value = GetNamedProperty(env, object, propertyName);
240     return GetStringFromValueUtf8(env, value);
241 }
242 
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)243 void NapiScanUtils::SetStringPropertyUtf8(
244     napi_env env, napi_value object, const std::string &name, const std::string &value)
245 {
246     if (object == nullptr) {
247         return;
248     }
249     napi_value jsValue = CreateStringUtf8(env, value);
250     if (GetValueType(env, jsValue) != napi_string) {
251         return;
252     }
253     napi_set_named_property(env, object, name.c_str(), jsValue);
254 }
255 
256 /* array buffer */
257 
CreateArrayBuffer(napi_env env,size_t length,void ** data)258 napi_value NapiScanUtils::CreateArrayBuffer(napi_env env, size_t length, void **data)
259 {
260     napi_value object = nullptr;
261     SCAN_CALL(env, napi_create_arraybuffer(env, length, data, &object));
262     return object;
263 }
264 
ValueIsArrayBuffer(napi_env env,napi_value value)265 bool NapiScanUtils::ValueIsArrayBuffer(napi_env env, napi_value value)
266 {
267     if (value == nullptr) {
268         return false;
269     }
270     bool isArrayBuffer = false;
271     SCAN_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
272     return isArrayBuffer;
273 }
274 
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)275 void *NapiScanUtils::GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
276 {
277     if (value == nullptr || length == nullptr) {
278         return nullptr;
279     }
280 
281     void *data = nullptr;
282     SCAN_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
283     return data;
284 }
285 
286 /* object */
CreateObject(napi_env env)287 napi_value NapiScanUtils::CreateObject(napi_env env)
288 {
289     napi_value object = nullptr;
290     SCAN_CALL(env, napi_create_object(env, &object));
291     return object;
292 }
293 
294 /* undefined */
GetUndefined(napi_env env)295 napi_value NapiScanUtils::GetUndefined(napi_env env)
296 {
297     napi_value undefined = nullptr;
298     SCAN_CALL(env, napi_get_undefined(env, &undefined));
299     return undefined;
300 }
301 
302 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)303 napi_value NapiScanUtils::CallFunction(
304     napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
305 {
306     if (func == nullptr) {
307         return nullptr;
308     }
309     napi_value res = nullptr;
310     SCAN_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
311     return res;
312 }
313 
314 /* reference */
CreateReference(napi_env env,napi_value callback)315 napi_ref NapiScanUtils::CreateReference(napi_env env, napi_value callback)
316 {
317     if (callback == nullptr) {
318         return nullptr;
319     }
320     napi_ref callbackRef = nullptr;
321     SCAN_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
322     return callbackRef;
323 }
324 
GetReference(napi_env env,napi_ref callbackRef)325 napi_value NapiScanUtils::GetReference(napi_env env, napi_ref callbackRef)
326 {
327     if (callbackRef == nullptr) {
328         return nullptr;
329     }
330     napi_value callback = nullptr;
331     SCAN_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
332     return callback;
333 }
334 
DeleteReference(napi_env env,napi_ref callbackRef)335 void NapiScanUtils::DeleteReference(napi_env env, napi_ref callbackRef)
336 {
337     if (env != nullptr && callbackRef != nullptr) {
338         (void)napi_delete_reference(env, callbackRef);
339     }
340 }
341 
342 /* boolean */
CreateBoolean(napi_env env,bool value)343 napi_value NapiScanUtils::CreateBoolean(napi_env env, bool value)
344 {
345     napi_value jsValue = nullptr;
346     if (napi_get_boolean(env, value, &jsValue) != napi_ok) {
347         return nullptr;
348     }
349     return jsValue;
350 }
351 
GetBooleanFromValue(napi_env env,napi_value value)352 bool NapiScanUtils::GetBooleanFromValue(napi_env env, napi_value value)
353 {
354     if (value == nullptr) {
355         return false;
356     }
357     bool ret = false;
358     SCAN_CALL_BASE(env, napi_get_value_bool(env, value, &ret), 0);
359     return ret;
360 }
361 
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)362 bool NapiScanUtils::GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
363 {
364     if (object == nullptr) {
365         return false;
366     }
367     if (!HasNamedProperty(env, object, propertyName)) {
368         return false;
369     }
370     napi_value value = GetNamedProperty(env, object, propertyName);
371     bool ret = false;
372     SCAN_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
373     return ret;
374 }
375 
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)376 void NapiScanUtils::SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
377 {
378     if (object == nullptr) {
379         return;
380     }
381     napi_value jsValue = nullptr;
382     SCAN_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
383     if (GetValueType(env, jsValue) != napi_boolean) {
384         return;
385     }
386 
387     napi_set_named_property(env, object, name.c_str(), jsValue);
388 }
389 
390 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)391 void NapiScanUtils::DefineProperties(
392     napi_env env, napi_value object, const std::initializer_list<napi_property_descriptor> &properties)
393 {
394     napi_property_descriptor descriptors[properties.size()];
395     std::copy(properties.begin(), properties.end(), descriptors);
396 
397     (void)napi_define_properties(env, object, properties.size(), descriptors);
398 }
399 
ToLower(const std::string & s)400 std::string NapiScanUtils::ToLower(const std::string &s)
401 {
402     std::string res = s;
403     std::transform(res.begin(), res.end(), res.begin(), tolower);
404     return res;
405 }
406 
GetValueString(napi_env env,napi_value value)407 std::string NapiScanUtils::GetValueString(napi_env env, napi_value value)
408 {
409     if (value == nullptr) {
410         return "";
411     }
412     std::string resultValue = "";
413     char value_string[256] = { 0 };
414     size_t value_size = 256;
415     size_t result = 0;
416     napi_status status = napi_get_value_string_utf8(env, value, value_string, value_size, &result);
417     if (status == napi_ok && result > 0) {
418         resultValue = value_string;
419     }
420     return resultValue;
421 }
422 
GetExtensionId(const std::string & globalId)423 std::string NapiScanUtils::GetExtensionId(const std::string &globalId)
424 {
425     auto pos = globalId.find(GLOBAL_ID_DELIMITER);
426     if (pos == std::string::npos) {
427         return "";
428     }
429     return globalId.substr(0, pos);
430 }
431 
GetGlobalId(const std::string & extensionId,const std::string & localId)432 std::string NapiScanUtils::GetGlobalId(const std::string& extensionId, const std::string& localId)
433 {
434     return extensionId + GLOBAL_ID_DELIMITER + localId;
435 }
436 
GetLocalId(const std::string & globalId,const std::string & extensionId)437 std::string NapiScanUtils::GetLocalId(const std::string& globalId, const std::string& extensionId)
438 {
439     auto pos = globalId.find(GLOBAL_ID_DELIMITER);
440     if (pos == std::string::npos) {
441         return "";
442     }
443 
444     if (globalId.substr(0, pos) != extensionId) {
445         return "";
446     }
447     return globalId.substr(pos + 1);
448 }
449 
EncodeExtensionCid(const std::string & extensionId,uint32_t callbackId)450 std::string NapiScanUtils::EncodeExtensionCid(const std::string &extensionId, uint32_t callbackId)
451 {
452     return extensionId + EXTENSION_CID_DELIMITER + std::to_string(callbackId);
453 }
454 
DecodeExtensionCid(const std::string & cid,std::string & extensionId,uint32_t & callbackId)455 bool NapiScanUtils::DecodeExtensionCid(const std::string &cid, std::string &extensionId, uint32_t &callbackId)
456 {
457     auto pos = cid.find(EXTENSION_CID_DELIMITER);
458     if (pos == std::string::npos) {
459         return false;
460     }
461     extensionId = cid.substr(0, pos);
462     int32_t callbackIdTmp = 0;
463     if (!ScanUtil::ConvertToInt(cid.substr(pos + 1), callbackIdTmp)) {
464         return false;
465     }
466     callbackId = static_cast<uint32_t>(callbackIdTmp);
467     return true;
468 }
469 
OpenFile(const std::string & filePath)470 int32_t NapiScanUtils::OpenFile(const std::string &filePath)
471 {
472     if (!IsPathValid(filePath)) {
473         return SCAN_INVALID_ID;
474     }
475     int32_t fd = open(filePath.c_str(), O_RDONLY);
476     SCAN_HILOGD("fd: %{public}d", fd);
477     if (fd < 0) {
478         SCAN_HILOGE("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
479         return SCAN_INVALID_ID;
480     }
481     return fd;
482 }
483 
IsPathValid(const std::string & filePath)484 bool NapiScanUtils::IsPathValid(const std::string &filePath)
485 {
486     auto path = filePath.substr(0, filePath.rfind('/'));
487     char resolvedPath[PATH_MAX + 1] = { 0 };
488     if (path.length() > PATH_MAX || realpath(path.c_str(), resolvedPath) == nullptr ||
489         strncmp(resolvedPath, path.c_str(), path.length()) != 0) {
490         SCAN_HILOGE("invalid file path!");
491         return false;
492     }
493     return true;
494 }
495 
GetIdFromFdPath(const std::string & fdPath)496 uint32_t NapiScanUtils::GetIdFromFdPath(const std::string &fdPath)
497 {
498     std::string fd_str = fdPath.substr(fdPath.rfind('/') + 1, fdPath.length());
499     std::stringstream getStrStream(fd_str);
500     uint32_t fd = 0;
501     if (!(getStrStream >> fd)) {
502         SCAN_HILOGD("failed to convert to uint32");
503     }
504     return fd;
505 }
506 
GetJsVal(napi_env env,napi_callback_info info,napi_value argv[],size_t length)507 size_t NapiScanUtils::GetJsVal(napi_env env, napi_callback_info info, napi_value argv[], size_t length)
508 {
509     size_t argc = length;
510     napi_value thisVal = nullptr;
511     void *data = nullptr;
512     napi_get_cb_info(env, info, &argc, argv, &thisVal, &data);
513     return argc;
514 }
515 
NapiThrowError(napi_env env,uint32_t errCode)516 void NapiScanUtils::NapiThrowError(napi_env env, uint32_t errCode)
517 {
518     std::string message;
519     SetErrorText(errCode, message);
520     napi_value result = nullptr;
521     napi_create_error(env, CreateUint32(env, errCode), CreateStringUtf8(env, message), &result);
522     napi_throw(env, result);
523 }
524 
SetErrorText(uint32_t & code,std::string & message)525 void NapiScanUtils::SetErrorText(uint32_t& code, std::string& message)
526 {
527     auto it = scanErrorCodeMap_.find(code);
528     if (it != scanErrorCodeMap_.end()) {
529         message = it->second;
530     } else {
531         SCAN_HILOGD("ErrorText not found");
532         code = E_SCAN_GENERIC_FAILURE;
533         message = "SCAN_ERROR_GENERIC_FAILURE";
534     }
535 }
536 
CheckCallerIsSystemApp()537 bool NapiScanUtils::CheckCallerIsSystemApp()
538 {
539     auto callerToken = IPCSkeleton::GetCallingTokenID();
540     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
541     if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
542         tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
543         SCAN_HILOGD("tokenType check passed.");
544         return true;
545     }
546     auto accessTokenId = IPCSkeleton::GetCallingFullTokenID();
547     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenId);
548 }
549 } // namespace OHOS::Scan
550