• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #define LOG_TAG "NapiRdbJsUtils"
16 #include "napi_rdb_js_utils.h"
17 
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21 #include <tuple>
22 
23 #include "js_ability.h"
24 #include "js_native_api_types.h"
25 #include "logger.h"
26 #include "rdb_errno.h"
27 #include "rdb_sql_statistic.h"
28 #include "rdb_sql_utils.h"
29 #include "rdb_types.h"
30 #include "result_set.h"
31 #include "transaction.h"
32 
33 #define NAPI_CALL_RETURN_ERR(theCall, retVal) \
34     do {                                      \
35         if ((theCall) != napi_ok) {           \
36             return retVal;                    \
37         }                                     \
38     } while (0)
39 
40 #ifndef PATH_SPLIT
41 #define PATH_SPLIT '/'
42 #endif
43 namespace OHOS::AppDataMgrJsKit {
44 namespace JSUtils {
45 using namespace OHOS::Rdb;
46 using namespace NativeRdb;
47 using RelationalStoreJsKit::ParamError;
48 using namespace RelationalStoreJsKit;
49 template<>
Convert2Value(napi_env env,napi_value jsValue,Asset & output)50 int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output)
51 {
52     napi_valuetype type = napi_undefined;
53     napi_status status = napi_typeof(env, jsValue, &type);
54     bool isArray;
55     napi_status status_array = napi_is_array(env, jsValue, &isArray);
56     if (status != napi_ok || type != napi_object || status_array != napi_ok || isArray) {
57         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
58         return napi_invalid_arg;
59     }
60 
61     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "name", output.name), napi_invalid_arg);
62     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "uri", output.uri), napi_invalid_arg);
63     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "createTime", output.createTime), napi_invalid_arg);
64     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "modifyTime", output.modifyTime), napi_invalid_arg);
65     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "size", output.size), napi_invalid_arg);
66     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "path", output.path), napi_invalid_arg);
67     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "status", output.status, true), napi_invalid_arg);
68     if (output.status != AssetValue::STATUS_DELETE) {
69         output.status = AssetValue::STATUS_UNKNOWN;
70     }
71     output.hash = output.modifyTime + "_" + output.size;
72     return napi_ok;
73 }
74 
75 template<>
Convert2Value(napi_env env,napi_value input,DistributedRdb::Reference & output)76 int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::Reference &output)
77 {
78     napi_valuetype type = napi_undefined;
79     napi_status status = napi_typeof(env, input, &type);
80     if (status != napi_ok || type != napi_object) {
81         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
82         return napi_invalid_arg;
83     }
84 
85     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "sourceTable", output.sourceTable), napi_invalid_arg);
86     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "targetTable", output.targetTable), napi_invalid_arg);
87     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "refFields", output.refFields), napi_invalid_arg);
88     return napi_ok;
89 }
90 
91 template<>
Convert2Value(napi_env env,napi_value input,DistributedRdb::DistributedConfig & output)92 int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::DistributedConfig &output)
93 {
94     napi_valuetype type = napi_undefined;
95     napi_status status = napi_typeof(env, input, &type);
96     if (status != napi_ok || type != napi_object) {
97         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
98         return napi_invalid_arg;
99     }
100 
101     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "autoSync", output.autoSync), napi_invalid_arg);
102     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "references", output.references, true), napi_invalid_arg);
103     NAPI_CALL_RETURN_ERR(
104         GetNamedProperty(env, input, "asyncDownloadAsset", output.asyncDownloadAsset, true), napi_invalid_arg);
105     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "enableCloud", output.enableCloud, true), napi_invalid_arg);
106     return napi_ok;
107 }
108 
109 template<>
Convert2Value(napi_env env,napi_value jsValue,ValueObject & valueObject)110 int32_t Convert2Value(napi_env env, napi_value jsValue, ValueObject &valueObject)
111 {
112     auto status = Convert2Value(env, jsValue, valueObject.value);
113     if (status != napi_ok) {
114         return napi_invalid_arg;
115     }
116     return napi_ok;
117 }
118 
119 template<>
Convert2JSValue(napi_env env,const Asset & value)120 napi_value Convert2JSValue(napi_env env, const Asset &value)
121 {
122     auto outputStatus = value.status & ~0xF0000000;
123     std::vector<napi_property_descriptor> descriptors = {
124         DECLARE_JS_PROPERTY(env, "name", value.name),
125         DECLARE_JS_PROPERTY(env, "uri", value.uri),
126         DECLARE_JS_PROPERTY(env, "createTime", value.createTime),
127         DECLARE_JS_PROPERTY(env, "modifyTime", value.modifyTime),
128         DECLARE_JS_PROPERTY(env, "size", value.size),
129         DECLARE_JS_PROPERTY(env, "path", value.path),
130         DECLARE_JS_PROPERTY(env, "status", outputStatus),
131     };
132 
133     napi_value object = nullptr;
134     NAPI_CALL_RETURN_ERR(
135         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
136     return object;
137 }
138 
139 template<>
Convert2JSValue(napi_env env,const RowEntity & rowEntity)140 napi_value Convert2JSValue(napi_env env, const RowEntity &rowEntity)
141 {
142     napi_value object = nullptr;
143     NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
144     auto &values = rowEntity.Get();
145     for (auto const &[key, value] : values) {
146         NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, key.c_str(), value), object);
147     }
148     return object;
149 }
150 
151 template<>
Convert2JSValue(napi_env env,const ValueObject & value)152 napi_value Convert2JSValue(napi_env env, const ValueObject &value)
153 {
154     return Convert2JSValue(env, value.value);
155 }
156 
157 template<>
Convert2JSValue(napi_env env,const DistributedRdb::Statistic & value)158 napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value)
159 {
160     std::vector<napi_property_descriptor> descriptors = {
161         DECLARE_JS_PROPERTY(env, "total", value.total),
162         DECLARE_JS_PROPERTY(env, "success", value.success),
163         DECLARE_JS_PROPERTY(env, "successful", value.success),
164         DECLARE_JS_PROPERTY(env, "failed", value.failed),
165         DECLARE_JS_PROPERTY(env, "remained", value.untreated),
166     };
167 
168     napi_value object = nullptr;
169     NAPI_CALL_RETURN_ERR(
170         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
171     return object;
172 }
173 
174 template<>
Convert2JSValue(napi_env env,const DistributedRdb::TableDetail & value)175 napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value)
176 {
177     std::vector<napi_property_descriptor> descriptors = {
178         DECLARE_JS_PROPERTY(env, "upload", value.upload),
179         DECLARE_JS_PROPERTY(env, "download", value.download),
180     };
181 
182     napi_value object = nullptr;
183     NAPI_CALL_RETURN_ERR(
184         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
185     return object;
186 }
187 
188 template<>
Convert2JSValue(napi_env env,const DistributedRdb::ProgressDetail & value)189 napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value)
190 {
191     std::vector<napi_property_descriptor> descriptors = {
192         DECLARE_JS_PROPERTY(env, "schedule", value.progress),
193         DECLARE_JS_PROPERTY(env, "code", value.code),
194         DECLARE_JS_PROPERTY(env, "details", value.details),
195     };
196 
197     napi_value object = nullptr;
198     NAPI_CALL_RETURN_ERR(
199         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
200     return object;
201 }
202 
203 template<>
Convert2JSValue(napi_env env,const DistributedRdb::SqlObserver::SqlExecutionInfo & value)204 napi_value Convert2JSValue(napi_env env, const DistributedRdb::SqlObserver::SqlExecutionInfo &value)
205 {
206     std::vector<napi_property_descriptor> descriptors = {
207         DECLARE_JS_PROPERTY(env, "sql", value.sql_),
208         DECLARE_JS_PROPERTY(env, "totalTime", value.totalTime_),
209         DECLARE_JS_PROPERTY(env, "waitTime", value.waitTime_),
210         DECLARE_JS_PROPERTY(env, "prepareTime", value.prepareTime_),
211         DECLARE_JS_PROPERTY(env, "executeTime", value.executeTime_),
212     };
213 
214     napi_value object = nullptr;
215     NAPI_CALL_RETURN_ERR(
216         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
217     return object;
218 }
219 
220 template<>
Convert2JSValue(napi_env env,const ExceptionMessage & value)221 napi_value Convert2JSValue(napi_env env, const ExceptionMessage &value)
222 {
223     std::vector<napi_property_descriptor> descriptors = {
224         DECLARE_JS_PROPERTY(env, "code", value.code),
225         DECLARE_JS_PROPERTY(env, "message", value.message),
226         DECLARE_JS_PROPERTY(env, "sql", value.sql),
227     };
228 
229     napi_value object = nullptr;
230     NAPI_CALL_RETURN_ERR(
231         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
232     return object;
233 }
234 
235 template<>
Convert2JSValue(napi_env env,const SqlInfo & sqlInfo)236 napi_value Convert2JSValue(napi_env env, const SqlInfo &sqlInfo)
237 {
238     std::vector<napi_property_descriptor> descriptors = {
239         DECLARE_JS_PROPERTY(env, "sql", sqlInfo.sql),
240         DECLARE_JS_PROPERTY(env, "args", sqlInfo.args),
241     };
242 
243     napi_value object = nullptr;
244     NAPI_CALL_RETURN_ERR(
245         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
246     return object;
247 }
248 
249 template<>
Convert2JSValue(napi_env env,const DistributedRdb::Details & details)250 napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details)
251 {
252     return nullptr;
253 }
254 
255 template<>
Convert2JSValue(napi_env env,const JSChangeInfo & value)256 napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value)
257 {
258     std::vector<napi_property_descriptor> descriptors = {
259         DECLARE_JS_PROPERTY(env, "table", value.table),
260         DECLARE_JS_PROPERTY(env, "type", value.type),
261         DECLARE_JS_PROPERTY(env, "inserted", value.inserted),
262         DECLARE_JS_PROPERTY(env, "updated", value.updated),
263         DECLARE_JS_PROPERTY(env, "deleted", value.deleted),
264     };
265 
266     napi_value object = nullptr;
267     NAPI_CALL_RETURN_ERR(
268         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
269     return object;
270 }
271 
272 template<>
Convert2JSValue(napi_env env,const Date & date)273 napi_value Convert2JSValue(napi_env env, const Date &date)
274 {
275     napi_value jsDeta = nullptr;
276     NAPI_CALL_RETURN_ERR(napi_create_date(env, date, &jsDeta), jsDeta);
277     return jsDeta;
278 }
279 template<>
Convert2JSValue(napi_env env,const BigInt & value)280 napi_value Convert2JSValue(napi_env env, const BigInt &value)
281 {
282     napi_value val = nullptr;
283     napi_status status = napi_create_bigint_words(env, value.Sign(), value.Size(), value.TrueForm(), &val);
284     if (status != napi_ok) {
285         return nullptr;
286     }
287     return val;
288 }
289 
290 template<>
Convert2Value(napi_env env,napi_value jsValue,BigInt & value)291 int32_t Convert2Value(napi_env env, napi_value jsValue, BigInt &value)
292 {
293     napi_valuetype type = napi_undefined;
294     napi_status status = napi_typeof(env, jsValue, &type);
295     if (status != napi_ok || type != napi_bigint) {
296         return napi_invalid_arg;
297     }
298     int sign = 0;
299     size_t count = 0;
300     status = napi_get_value_bigint_words(env, jsValue, nullptr, &count, nullptr);
301     if (status != napi_ok) {
302         return napi_bigint_expected;
303     }
304     std::vector<uint64_t> words(count, 0);
305     status = napi_get_value_bigint_words(env, jsValue, &sign, &count, words.data());
306     if (status != napi_ok) {
307         return napi_bigint_expected;
308     }
309     value = BigInteger(sign, std::move(words));
310     return napi_ok;
311 }
312 
313 template<>
ToString(const PRIKey & key)314 std::string ToString(const PRIKey &key)
315 {
316     auto strVal = std::get_if<std::string>(&key);
317     if (strVal != nullptr) {
318         return *strVal;
319     }
320     auto intVal = std::get_if<int64_t>(&key);
321     if (intVal != nullptr) {
322         return std::to_string(*intVal);
323     }
324     auto dbVal = std::get_if<double>(&key);
325     if (dbVal != nullptr) {
326         return std::to_string(static_cast<int64_t>(*dbVal));
327     }
328     return {};
329 }
330 
IsNapiString(napi_env env,napi_value value)331 bool IsNapiString(napi_env env, napi_value value)
332 {
333     napi_valuetype type = napi_undefined;
334     NAPI_CALL_BASE(env, napi_typeof(env, value, &type), false);
335     return type == napi_string;
336 }
337 
GetLevel(SecurityLevel level,SecurityLevel & out)338 int32_t GetLevel(SecurityLevel level, SecurityLevel &out)
339 {
340     switch (level) {
341         case SecurityLevel::S1:
342         case SecurityLevel::S2:
343         case SecurityLevel::S3:
344         case SecurityLevel::S4:
345             out = level;
346             return napi_ok;
347         default:
348             return napi_invalid_arg;
349     }
350 }
351 
352 template<>
Convert2Value(napi_env env,napi_value input,CryptoParam & cryptoParam)353 int32_t Convert2Value(napi_env env, napi_value input, CryptoParam &cryptoParam)
354 {
355     napi_valuetype type = napi_undefined;
356     napi_status status = napi_typeof(env, input, &type);
357     if (status != napi_ok || type != napi_object) {
358         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
359         return napi_invalid_arg;
360     }
361 
362     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "encryptionKey", cryptoParam.encryptKey_), napi_invalid_arg);
363     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "iterationCount", cryptoParam.iterNum, true), napi_invalid_arg);
364     NAPI_CALL_RETURN_ERR(
365         GetNamedProperty(env, input, "encryptionAlgo", cryptoParam.encryptAlgo, true), napi_invalid_arg);
366     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "hmacAlgo", cryptoParam.hmacAlgo, true), napi_invalid_arg);
367     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "kdfAlgo", cryptoParam.kdfAlgo, true), napi_invalid_arg);
368     NAPI_CALL_RETURN_ERR(
369         GetNamedProperty(env, input, "cryptoPageSize", cryptoParam.cryptoPageSize, true), napi_invalid_arg);
370 
371     return napi_ok;
372 }
373 
374 template<>
Convert2Value(napi_env env,napi_value jsValue,RdbConfig & rdbConfig)375 int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig)
376 {
377     int32_t status = GetNamedProperty(env, jsValue, "encrypt", rdbConfig.isEncrypt, true);
378     ASSERT(OK == status, "get encrypt failed.", napi_invalid_arg);
379 
380     int32_t securityLevel;
381     status = GetNamedProperty(env, jsValue, "securityLevel", securityLevel);
382     ASSERT(OK == status, "get securityLevel failed.", napi_invalid_arg);
383     status = GetLevel(static_cast<SecurityLevel>(securityLevel), rdbConfig.securityLevel);
384     ASSERT(status == napi_ok, "get securityLevel failed", status);
385 
386     status = GetNamedProperty(env, jsValue, "dataGroupId", rdbConfig.dataGroupId, true);
387     ASSERT(OK == status, "get dataGroupId failed.", napi_invalid_arg);
388 
389     status = GetNamedProperty(env, jsValue, "autoCleanDirtyData", rdbConfig.isAutoClean, true);
390     ASSERT(OK == status, "get autoCleanDirtyData failed.", napi_invalid_arg);
391 
392     status = GetNamedProperty(env, jsValue, "name", rdbConfig.name);
393     ASSERT(OK == status, "get name failed.", napi_invalid_arg);
394 
395     status = GetNamedProperty(env, jsValue, "customDir", rdbConfig.customDir, true);
396     ASSERT(OK == status, "get customDir failed.", napi_invalid_arg);
397 
398     status = GetNamedProperty(env, jsValue, "rootDir", rdbConfig.rootDir, true);
399     ASSERT(OK == status, "get rootDir failed.", napi_invalid_arg);
400 
401     GetNamedProperty(env, jsValue, "isSearchable", rdbConfig.isSearchable, true);
402     ASSERT(OK == status, "get isSearchable failed.", napi_invalid_arg);
403 
404     GetNamedProperty(env, jsValue, "vector", rdbConfig.vector, true);
405     ASSERT(OK == status, "get vector failed.", napi_invalid_arg);
406 
407     GetNamedProperty(env, jsValue, "allowRebuild", rdbConfig.allowRebuild, true);
408     ASSERT(OK == status, "get allowRebuild failed.", napi_invalid_arg);
409 
410     GetNamedProperty(env, jsValue, "isReadOnly", rdbConfig.isReadOnly, true);
411     ASSERT(OK == status, "get isReadOnly failed.", napi_invalid_arg);
412 
413     GetNamedProperty(env, jsValue, "pluginLibs", rdbConfig.pluginLibs, true);
414     ASSERT(OK == status, "get pluginLibs failed.", napi_invalid_arg);
415 
416     status = GetNamedProperty(env, jsValue, "haMode", rdbConfig.haMode, true);
417     ASSERT(OK == status, "get haMode failed.", napi_invalid_arg);
418 
419     status = GetNamedProperty(env, jsValue, "cryptoParam", rdbConfig.cryptoParam, true);
420     ASSERT(OK == status, "get cryptoParam failed.", napi_invalid_arg);
421 
422     int32_t tokenizer = static_cast<int32_t>(Tokenizer::NONE_TOKENIZER);
423     status = GetNamedProperty(env, jsValue, "tokenizer", tokenizer, true);
424     ASSERT(OK == status, "get tokenizer failed.", napi_invalid_arg);
425     rdbConfig.tokenizer = static_cast<Tokenizer>(tokenizer);
426 
427     status = GetNamedProperty(env, jsValue, "persist", rdbConfig.persist, true);
428     ASSERT(OK == status, "get persist failed.", napi_invalid_arg);
429 
430     status = GetNamedProperty(env, jsValue, "enableSemanticIndex", rdbConfig.enableSemanticIndex, true);
431     ASSERT(OK == status, "get enableSemanticIndex failed.", napi_invalid_arg);
432     return napi_ok;
433 }
434 
435 template<>
Convert2Value(napi_env env,napi_value jsValue,TransactionOptions & transactionOptions)436 int32_t Convert2Value(napi_env env, napi_value jsValue, TransactionOptions &transactionOptions)
437 {
438     int32_t status = GetNamedProperty(env, jsValue, "transactionType", transactionOptions.transactionType, true);
439     bool checked = transactionOptions.transactionType >= Transaction::DEFERRED &&
440                    transactionOptions.transactionType <= Transaction::EXCLUSIVE;
441     ASSERT(OK == status && checked, "get transactionType failed.", napi_invalid_arg);
442     return napi_ok;
443 }
444 
GetCurrentAbilityParam(napi_env env,napi_value jsValue,ContextParam & param)445 int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam &param)
446 {
447     std::shared_ptr<Context> context = JSAbility::GetCurrentAbility(env, jsValue);
448     if (context == nullptr) {
449         return napi_invalid_arg;
450     }
451     param.baseDir = context->GetDatabaseDir();
452     param.moduleName = context->GetModuleName();
453     param.area = context->GetArea();
454     param.bundleName = context->GetBundleName();
455     param.isSystemApp = context->IsSystemAppCalled();
456     return napi_ok;
457 }
458 
459 template<>
Convert2Value(napi_env env,napi_value jsValue,ContextParam & param)460 int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam &param)
461 {
462     if (jsValue == nullptr) {
463         LOG_INFO("hasProp is false -> fa stage");
464         param.isStageMode = false;
465         return GetCurrentAbilityParam(env, jsValue, param);
466     }
467 
468     int32_t status = GetNamedProperty(env, jsValue, "stageMode", param.isStageMode);
469     ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg);
470     if (!param.isStageMode) {
471         LOG_WARN("isStageMode is false -> fa stage");
472         return GetCurrentAbilityParam(env, jsValue, param);
473     }
474     LOG_DEBUG("Stage mode branch");
475     status = GetNamedProperty(env, jsValue, "databaseDir", param.baseDir);
476     ASSERT(status == napi_ok, "get databaseDir failed.", napi_invalid_arg);
477     status = GetNamedProperty(env, jsValue, "area", param.area, true);
478     ASSERT(status == napi_ok, "get area failed.", napi_invalid_arg);
479 
480     napi_value hapInfo = nullptr;
481     GetNamedProperty(env, jsValue, "currentHapModuleInfo", hapInfo);
482     if (hapInfo != nullptr) {
483         status = GetNamedProperty(env, hapInfo, "name", param.moduleName);
484         ASSERT(status == napi_ok, "get currentHapModuleInfo.name failed.", napi_invalid_arg);
485     }
486 
487     napi_value appInfo = nullptr;
488     GetNamedProperty(env, jsValue, "applicationInfo", appInfo);
489     if (appInfo != nullptr) {
490         status = GetNamedProperty(env, appInfo, "name", param.bundleName);
491         ASSERT(status == napi_ok, "get applicationInfo.name failed.", napi_invalid_arg);
492         status = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp, true);
493         ASSERT(status == napi_ok, "get applicationInfo.systemApp failed.", napi_invalid_arg);
494         int32_t hapVersion = JSAbility::GetHapVersion(env, jsValue);
495         JSUtils::SetHapVersion(hapVersion);
496     }
497     return napi_ok;
498 }
499 
GetRealPath(napi_env env,napi_value jsValue,RdbConfig & rdbConfig,ContextParam & param)500 std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(
501     napi_env env, napi_value jsValue, RdbConfig &rdbConfig, ContextParam &param)
502 {
503     CHECK_RETURN_CORE(rdbConfig.name.find(PATH_SPLIT) == std::string::npos, RDB_DO_NOTHING,
504         std::make_tuple(ERR, std::make_shared<ParamError>("StoreConfig.name", "a file name without path.")));
505 
506     if (!rdbConfig.customDir.empty()) {
507         // determine if the first character of customDir is '/'
508         CHECK_RETURN_CORE(rdbConfig.customDir.find_first_of(PATH_SPLIT) != 0, RDB_DO_NOTHING,
509             std::make_tuple(ERR, std::make_shared<ParamError>("customDir", "a relative directory.")));
510         // customDir length is limited to 128 bytes
511         CHECK_RETURN_CORE(rdbConfig.customDir.length() <= 128, RDB_DO_NOTHING,
512             std::make_tuple(ERR, std::make_shared<ParamError>("customDir length", "less than or equal to 128 "
513                                                                                   "bytes.")));
514     }
515 
516     std::string baseDir = param.baseDir;
517     if (!rdbConfig.dataGroupId.empty()) {
518         if (!param.isStageMode) {
519             return std::make_tuple(ERR, std::make_shared<InnerError>(E_NOT_STAGE_MODE));
520         }
521         auto stageContext = JSAbility::GetStageModeContext(env, jsValue);
522         if (stageContext == nullptr) {
523             return std::make_tuple(ERR, std::make_shared<ParamError>("Illegal context."));
524         }
525         std::string groupDir;
526         int errCode = stageContext->GetSystemDatabaseDir(rdbConfig.dataGroupId, groupDir);
527         CHECK_RETURN_CORE(errCode == E_OK || !groupDir.empty(), RDB_DO_NOTHING,
528             std::make_tuple(ERR, std::make_shared<InnerError>(E_DATA_GROUP_ID_INVALID)));
529         baseDir = groupDir;
530     }
531 
532     if (!rdbConfig.rootDir.empty()) {
533         // determine if the first character of rootDir is '/'
534         CHECK_RETURN_CORE(rdbConfig.rootDir.find_first_of(PATH_SPLIT) == 0, RDB_DO_NOTHING,
535             std::make_tuple(ERR, std::make_shared<PathError>()));
536         auto [realPath, errorCode] =
537             RdbSqlUtils::GetCustomDatabasePath(rdbConfig.rootDir, rdbConfig.name, rdbConfig.customDir);
538         CHECK_RETURN_CORE(errorCode == E_OK, RDB_DO_NOTHING,
539             std::make_tuple(ERR, std::make_shared<PathError>()));
540         rdbConfig.path = realPath;
541         return std::make_tuple(E_OK, nullptr);
542     }
543 
544     auto [realPath, errorCode] = RdbSqlUtils::GetDefaultDatabasePath(baseDir, rdbConfig.name, rdbConfig.customDir);
545     // realPath length is limited to 1024 bytes
546     CHECK_RETURN_CORE(errorCode == E_OK && realPath.length() <= 1024, RDB_DO_NOTHING,
547         std::make_tuple(ERR, std::make_shared<ParamError>("database path", "a valid path.")));
548     rdbConfig.path = realPath;
549     return std::make_tuple(E_OK, nullptr);
550 }
551 
GetRdbStoreConfig(const RdbConfig & rdbConfig,const ContextParam & param)552 RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam &param)
553 {
554     RdbStoreConfig rdbStoreConfig(rdbConfig.path);
555     rdbStoreConfig.SetEncryptStatus(rdbConfig.isEncrypt);
556     rdbStoreConfig.SetSearchable(rdbConfig.isSearchable);
557     rdbStoreConfig.SetIsVector(rdbConfig.vector);
558     rdbStoreConfig.SetDBType(rdbConfig.vector ? DB_VECTOR : DB_SQLITE);
559     rdbStoreConfig.SetStorageMode(rdbConfig.persist ? StorageMode::MODE_DISK : StorageMode::MODE_MEMORY);
560     rdbStoreConfig.SetAutoClean(rdbConfig.isAutoClean);
561     rdbStoreConfig.SetSecurityLevel(rdbConfig.securityLevel);
562     rdbStoreConfig.SetDataGroupId(rdbConfig.dataGroupId);
563     rdbStoreConfig.SetName(rdbConfig.name);
564     rdbStoreConfig.SetCustomDir(rdbConfig.customDir);
565     rdbStoreConfig.SetAllowRebuild(rdbConfig.allowRebuild);
566     rdbStoreConfig.SetReadOnly(rdbConfig.isReadOnly);
567     rdbStoreConfig.SetIntegrityCheck(IntegrityCheck::NONE);
568     rdbStoreConfig.SetTokenizer(rdbConfig.tokenizer);
569 
570     if (!param.bundleName.empty()) {
571         rdbStoreConfig.SetBundleName(param.bundleName);
572     }
573     rdbStoreConfig.SetModuleName(param.moduleName);
574     rdbStoreConfig.SetArea(param.area);
575     rdbStoreConfig.SetPluginLibs(rdbConfig.pluginLibs);
576     rdbStoreConfig.SetHaMode(rdbConfig.haMode);
577 
578     rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam);
579 
580     rdbStoreConfig.SetEnableSemanticIndex(rdbConfig.enableSemanticIndex);
581     return rdbStoreConfig;
582 }
583 
HasDuplicateAssets(const ValueObject & value)584 bool HasDuplicateAssets(const ValueObject &value)
585 {
586     auto *assets = std::get_if<ValueObject::Assets>(&value.value);
587     if (assets == nullptr) {
588         return false;
589     }
590     std::set<std::string> names;
591     auto item = assets->begin();
592     while (item != assets->end()) {
593         if (!names.insert(item->name).second) {
594             LOG_ERROR("Duplicate assets! name = %{public}.6s", item->name.c_str());
595             return true;
596         }
597         item++;
598     }
599     return false;
600 }
601 
HasDuplicateAssets(const std::vector<ValueObject> & values)602 bool HasDuplicateAssets(const std::vector<ValueObject> &values)
603 {
604     for (auto &val : values) {
605         if (HasDuplicateAssets(val)) {
606             return true;
607         }
608     }
609     return false;
610 }
611 
HasDuplicateAssets(const ValuesBucket & value)612 bool HasDuplicateAssets(const ValuesBucket &value)
613 {
614     for (auto &[key, val] : value.values_) {
615         if (HasDuplicateAssets(val)) {
616             return true;
617         }
618     }
619     return false;
620 }
621 
HasDuplicateAssets(const std::vector<ValuesBucket> & values)622 bool HasDuplicateAssets(const std::vector<ValuesBucket> &values)
623 {
624     for (auto &valueBucket : values) {
625         if (HasDuplicateAssets(valueBucket)) {
626             return true;
627         }
628     }
629     return false;
630 }
631 
HasDuplicateAssets(const ValuesBuckets & values)632 bool HasDuplicateAssets(const ValuesBuckets &values)
633 {
634     const auto &[fields, vals] = values.GetFieldsAndValues();
635     for (const auto &valueObject : *vals) {
636         if (HasDuplicateAssets(valueObject)) {
637             return true;
638         }
639     }
640     return false;
641 }
642 }; // namespace JSUtils
643 } // namespace OHOS::AppDataMgrJsKit