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 DistributedRdb::Details & details)221 napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details)
222 {
223 return nullptr;
224 }
225
226 template<>
Convert2JSValue(napi_env env,const JSChangeInfo & value)227 napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value)
228 {
229 std::vector<napi_property_descriptor> descriptors = {
230 DECLARE_JS_PROPERTY(env, "table", value.table),
231 DECLARE_JS_PROPERTY(env, "type", value.type),
232 DECLARE_JS_PROPERTY(env, "inserted", value.inserted),
233 DECLARE_JS_PROPERTY(env, "updated", value.updated),
234 DECLARE_JS_PROPERTY(env, "deleted", value.deleted),
235 };
236
237 napi_value object = nullptr;
238 NAPI_CALL_RETURN_ERR(
239 napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
240 return object;
241 }
242
243 template<>
Convert2JSValue(napi_env env,const Date & date)244 napi_value Convert2JSValue(napi_env env, const Date &date)
245 {
246 napi_value jsDeta = nullptr;
247 NAPI_CALL_RETURN_ERR(napi_create_date(env, date, &jsDeta), jsDeta);
248 return jsDeta;
249 }
250 template<>
Convert2JSValue(napi_env env,const BigInt & value)251 napi_value Convert2JSValue(napi_env env, const BigInt &value)
252 {
253 napi_value val = nullptr;
254 napi_status status = napi_create_bigint_words(env, value.Sign(), value.Size(), value.TrueForm(), &val);
255 if (status != napi_ok) {
256 return nullptr;
257 }
258 return val;
259 }
260
261 template<>
Convert2Value(napi_env env,napi_value jsValue,BigInt & value)262 int32_t Convert2Value(napi_env env, napi_value jsValue, BigInt &value)
263 {
264 napi_valuetype type = napi_undefined;
265 napi_status status = napi_typeof(env, jsValue, &type);
266 if (status != napi_ok || type != napi_bigint) {
267 return napi_invalid_arg;
268 }
269 int sign = 0;
270 size_t count = 0;
271 status = napi_get_value_bigint_words(env, jsValue, nullptr, &count, nullptr);
272 if (status != napi_ok) {
273 return napi_bigint_expected;
274 }
275 std::vector<uint64_t> words(count, 0);
276 status = napi_get_value_bigint_words(env, jsValue, &sign, &count, words.data());
277 if (status != napi_ok) {
278 return napi_bigint_expected;
279 }
280 value = BigInteger(sign, std::move(words));
281 return napi_ok;
282 }
283
284 template<>
ToString(const PRIKey & key)285 std::string ToString(const PRIKey &key)
286 {
287 auto strVal = std::get_if<std::string>(&key);
288 if (strVal != nullptr) {
289 return *strVal;
290 }
291 auto intVal = std::get_if<int64_t>(&key);
292 if (intVal != nullptr) {
293 return std::to_string(*intVal);
294 }
295 auto dbVal = std::get_if<double>(&key);
296 if (dbVal != nullptr) {
297 return std::to_string(static_cast<int64_t>(*dbVal));
298 }
299 return {};
300 }
301
IsNapiString(napi_env env,napi_value value)302 bool IsNapiString(napi_env env, napi_value value)
303 {
304 napi_valuetype type = napi_undefined;
305 NAPI_CALL_BASE(env, napi_typeof(env, value, &type), false);
306 return type == napi_string;
307 }
308
GetLevel(SecurityLevel level,SecurityLevel & out)309 int32_t GetLevel(SecurityLevel level, SecurityLevel &out)
310 {
311 switch (level) {
312 case SecurityLevel::S1:
313 case SecurityLevel::S2:
314 case SecurityLevel::S3:
315 case SecurityLevel::S4:
316 out = level;
317 return napi_ok;
318 default:
319 return napi_invalid_arg;
320 }
321 }
322
323 template<>
Convert2Value(napi_env env,napi_value input,CryptoParam & cryptoParam)324 int32_t Convert2Value(napi_env env, napi_value input, CryptoParam &cryptoParam)
325 {
326 napi_valuetype type = napi_undefined;
327 napi_status status = napi_typeof(env, input, &type);
328 if (status != napi_ok || type != napi_object) {
329 LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
330 return napi_invalid_arg;
331 }
332
333 NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "encryptionKey", cryptoParam.encryptKey_), napi_invalid_arg);
334 NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "iterationCount", cryptoParam.iterNum, true), napi_invalid_arg);
335 NAPI_CALL_RETURN_ERR(
336 GetNamedProperty(env, input, "encryptionAlgo", cryptoParam.encryptAlgo, true), napi_invalid_arg);
337 NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "hmacAlgo", cryptoParam.hmacAlgo, true), napi_invalid_arg);
338 NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "kdfAlgo", cryptoParam.kdfAlgo, true), napi_invalid_arg);
339 NAPI_CALL_RETURN_ERR(
340 GetNamedProperty(env, input, "cryptoPageSize", cryptoParam.cryptoPageSize, true), napi_invalid_arg);
341
342 return napi_ok;
343 }
344
345 template<>
Convert2Value(napi_env env,napi_value jsValue,RdbConfig & rdbConfig)346 int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig)
347 {
348 int32_t status = GetNamedProperty(env, jsValue, "encrypt", rdbConfig.isEncrypt, true);
349 ASSERT(OK == status, "get encrypt failed.", napi_invalid_arg);
350
351 int32_t securityLevel;
352 status = GetNamedProperty(env, jsValue, "securityLevel", securityLevel);
353 ASSERT(OK == status, "get securityLevel failed.", napi_invalid_arg);
354 status = GetLevel(static_cast<SecurityLevel>(securityLevel), rdbConfig.securityLevel);
355 ASSERT(status == napi_ok, "get securityLevel failed", status);
356
357 status = GetNamedProperty(env, jsValue, "dataGroupId", rdbConfig.dataGroupId, true);
358 ASSERT(OK == status, "get dataGroupId failed.", napi_invalid_arg);
359
360 status = GetNamedProperty(env, jsValue, "autoCleanDirtyData", rdbConfig.isAutoClean, true);
361 ASSERT(OK == status, "get autoCleanDirtyData failed.", napi_invalid_arg);
362
363 status = GetNamedProperty(env, jsValue, "name", rdbConfig.name);
364 ASSERT(OK == status, "get name failed.", napi_invalid_arg);
365
366 status = GetNamedProperty(env, jsValue, "customDir", rdbConfig.customDir, true);
367 ASSERT(OK == status, "get customDir failed.", napi_invalid_arg);
368
369 status = GetNamedProperty(env, jsValue, "rootDir", rdbConfig.rootDir, true);
370 ASSERT(OK == status, "get rootDir failed.", napi_invalid_arg);
371
372 GetNamedProperty(env, jsValue, "isSearchable", rdbConfig.isSearchable, true);
373 ASSERT(OK == status, "get isSearchable failed.", napi_invalid_arg);
374
375 GetNamedProperty(env, jsValue, "vector", rdbConfig.vector, true);
376 ASSERT(OK == status, "get vector failed.", napi_invalid_arg);
377
378 GetNamedProperty(env, jsValue, "allowRebuild", rdbConfig.allowRebuild, true);
379 ASSERT(OK == status, "get allowRebuild failed.", napi_invalid_arg);
380
381 GetNamedProperty(env, jsValue, "isReadOnly", rdbConfig.isReadOnly, true);
382 ASSERT(OK == status, "get isReadOnly failed.", napi_invalid_arg);
383
384 GetNamedProperty(env, jsValue, "pluginLibs", rdbConfig.pluginLibs, true);
385 ASSERT(OK == status, "get pluginLibs failed.", napi_invalid_arg);
386
387 status = GetNamedProperty(env, jsValue, "haMode", rdbConfig.haMode, true);
388 ASSERT(OK == status, "get haMode failed.", napi_invalid_arg);
389
390 status = GetNamedProperty(env, jsValue, "cryptoParam", rdbConfig.cryptoParam, true);
391 ASSERT(OK == status, "get cryptoParam failed.", napi_invalid_arg);
392
393 int32_t tokenizer = static_cast<int32_t>(Tokenizer::NONE_TOKENIZER);
394 status = GetNamedProperty(env, jsValue, "tokenizer", tokenizer, true);
395 ASSERT(OK == status, "get tokenizer failed.", napi_invalid_arg);
396 rdbConfig.tokenizer = static_cast<Tokenizer>(tokenizer);
397
398 status = GetNamedProperty(env, jsValue, "persist", rdbConfig.persist, true);
399 ASSERT(OK == status, "get persist failed.", napi_invalid_arg);
400 return napi_ok;
401 }
402
403 template<>
Convert2Value(napi_env env,napi_value jsValue,TransactionOptions & transactionOptions)404 int32_t Convert2Value(napi_env env, napi_value jsValue, TransactionOptions &transactionOptions)
405 {
406 int32_t status = GetNamedProperty(env, jsValue, "transactionType", transactionOptions.transactionType, true);
407 bool checked = transactionOptions.transactionType >= Transaction::DEFERRED &&
408 transactionOptions.transactionType <= Transaction::EXCLUSIVE;
409 ASSERT(OK == status && checked, "get transactionType failed.", napi_invalid_arg);
410 return napi_ok;
411 }
412
GetCurrentAbilityParam(napi_env env,napi_value jsValue,ContextParam & param)413 int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam ¶m)
414 {
415 std::shared_ptr<Context> context = JSAbility::GetCurrentAbility(env, jsValue);
416 if (context == nullptr) {
417 return napi_invalid_arg;
418 }
419 param.baseDir = context->GetDatabaseDir();
420 param.moduleName = context->GetModuleName();
421 param.area = context->GetArea();
422 param.bundleName = context->GetBundleName();
423 param.isSystemApp = context->IsSystemAppCalled();
424 return napi_ok;
425 }
426
427 template<>
Convert2Value(napi_env env,napi_value jsValue,ContextParam & param)428 int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam ¶m)
429 {
430 if (jsValue == nullptr) {
431 LOG_INFO("hasProp is false -> fa stage");
432 param.isStageMode = false;
433 return GetCurrentAbilityParam(env, jsValue, param);
434 }
435
436 int32_t status = GetNamedProperty(env, jsValue, "stageMode", param.isStageMode);
437 ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg);
438 if (!param.isStageMode) {
439 LOG_WARN("isStageMode is false -> fa stage");
440 return GetCurrentAbilityParam(env, jsValue, param);
441 }
442 LOG_DEBUG("Stage mode branch");
443 status = GetNamedProperty(env, jsValue, "databaseDir", param.baseDir);
444 ASSERT(status == napi_ok, "get databaseDir failed.", napi_invalid_arg);
445 status = GetNamedProperty(env, jsValue, "area", param.area, true);
446 ASSERT(status == napi_ok, "get area failed.", napi_invalid_arg);
447
448 napi_value hapInfo = nullptr;
449 GetNamedProperty(env, jsValue, "currentHapModuleInfo", hapInfo);
450 if (hapInfo != nullptr) {
451 status = GetNamedProperty(env, hapInfo, "name", param.moduleName);
452 ASSERT(status == napi_ok, "get currentHapModuleInfo.name failed.", napi_invalid_arg);
453 }
454
455 napi_value appInfo = nullptr;
456 GetNamedProperty(env, jsValue, "applicationInfo", appInfo);
457 if (appInfo != nullptr) {
458 status = GetNamedProperty(env, appInfo, "name", param.bundleName);
459 ASSERT(status == napi_ok, "get applicationInfo.name failed.", napi_invalid_arg);
460 status = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp, true);
461 ASSERT(status == napi_ok, "get applicationInfo.systemApp failed.", napi_invalid_arg);
462 int32_t hapVersion = JSAbility::GetHapVersion(env, jsValue);
463 JSUtils::SetHapVersion(hapVersion);
464 }
465 return napi_ok;
466 }
467
GetRealPath(napi_env env,napi_value jsValue,RdbConfig & rdbConfig,ContextParam & param)468 std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(
469 napi_env env, napi_value jsValue, RdbConfig &rdbConfig, ContextParam ¶m)
470 {
471 CHECK_RETURN_CORE(rdbConfig.name.find(PATH_SPLIT) == std::string::npos, RDB_DO_NOTHING,
472 std::make_tuple(ERR, std::make_shared<ParamError>("StoreConfig.name", "a file name without path.")));
473
474 if (!rdbConfig.customDir.empty()) {
475 // determine if the first character of customDir is '/'
476 CHECK_RETURN_CORE(rdbConfig.customDir.find_first_of(PATH_SPLIT) != 0, RDB_DO_NOTHING,
477 std::make_tuple(ERR, std::make_shared<ParamError>("customDir", "a relative directory.")));
478 // customDir length is limited to 128 bytes
479 CHECK_RETURN_CORE(rdbConfig.customDir.length() <= 128, RDB_DO_NOTHING,
480 std::make_tuple(ERR, std::make_shared<ParamError>("customDir length", "less than or equal to 128 "
481 "bytes.")));
482 }
483
484 std::string baseDir = param.baseDir;
485 if (!rdbConfig.dataGroupId.empty()) {
486 if (!param.isStageMode) {
487 return std::make_tuple(ERR, std::make_shared<InnerError>(E_NOT_STAGE_MODE));
488 }
489 auto stageContext = JSAbility::GetStageModeContext(env, jsValue);
490 if (stageContext == nullptr) {
491 return std::make_tuple(ERR, std::make_shared<ParamError>("Illegal context."));
492 }
493 std::string groupDir;
494 int errCode = stageContext->GetSystemDatabaseDir(rdbConfig.dataGroupId, groupDir);
495 CHECK_RETURN_CORE(errCode == E_OK || !groupDir.empty(), RDB_DO_NOTHING,
496 std::make_tuple(ERR, std::make_shared<InnerError>(E_DATA_GROUP_ID_INVALID)));
497 baseDir = groupDir;
498 }
499
500 if (!rdbConfig.rootDir.empty()) {
501 // determine if the first character of rootDir is '/'
502 CHECK_RETURN_CORE(rdbConfig.rootDir.find_first_of(PATH_SPLIT) == 0, RDB_DO_NOTHING,
503 std::make_tuple(ERR, std::make_shared<PathError>()));
504 auto [realPath, errorCode] =
505 RdbSqlUtils::GetCustomDatabasePath(rdbConfig.rootDir, rdbConfig.name, rdbConfig.customDir);
506 CHECK_RETURN_CORE(errorCode == E_OK, RDB_DO_NOTHING,
507 std::make_tuple(ERR, std::make_shared<PathError>()));
508 rdbConfig.path = realPath;
509 return std::make_tuple(E_OK, nullptr);
510 }
511
512 auto [realPath, errorCode] = RdbSqlUtils::GetDefaultDatabasePath(baseDir, rdbConfig.name, rdbConfig.customDir);
513 // realPath length is limited to 1024 bytes
514 CHECK_RETURN_CORE(errorCode == E_OK && realPath.length() <= 1024, RDB_DO_NOTHING,
515 std::make_tuple(ERR, std::make_shared<ParamError>("database path", "a valid path.")));
516 rdbConfig.path = realPath;
517 return std::make_tuple(E_OK, nullptr);
518 }
519
GetRdbStoreConfig(const RdbConfig & rdbConfig,const ContextParam & param)520 RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam ¶m)
521 {
522 RdbStoreConfig rdbStoreConfig(rdbConfig.path);
523 rdbStoreConfig.SetEncryptStatus(rdbConfig.isEncrypt);
524 rdbStoreConfig.SetSearchable(rdbConfig.isSearchable);
525 rdbStoreConfig.SetIsVector(rdbConfig.vector);
526 rdbStoreConfig.SetDBType(rdbConfig.vector ? DB_VECTOR : DB_SQLITE);
527 rdbStoreConfig.SetStorageMode(rdbConfig.persist ? StorageMode::MODE_DISK : StorageMode::MODE_MEMORY);
528 rdbStoreConfig.SetAutoClean(rdbConfig.isAutoClean);
529 rdbStoreConfig.SetSecurityLevel(rdbConfig.securityLevel);
530 rdbStoreConfig.SetDataGroupId(rdbConfig.dataGroupId);
531 rdbStoreConfig.SetName(rdbConfig.name);
532 rdbStoreConfig.SetCustomDir(rdbConfig.customDir);
533 rdbStoreConfig.SetAllowRebuild(rdbConfig.allowRebuild);
534 rdbStoreConfig.SetReadOnly(rdbConfig.isReadOnly);
535 rdbStoreConfig.SetIntegrityCheck(IntegrityCheck::NONE);
536 rdbStoreConfig.SetTokenizer(rdbConfig.tokenizer);
537
538 if (!param.bundleName.empty()) {
539 rdbStoreConfig.SetBundleName(param.bundleName);
540 }
541 rdbStoreConfig.SetModuleName(param.moduleName);
542 rdbStoreConfig.SetArea(param.area);
543 rdbStoreConfig.SetPluginLibs(rdbConfig.pluginLibs);
544 rdbStoreConfig.SetHaMode(rdbConfig.haMode);
545
546 rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam);
547 return rdbStoreConfig;
548 }
549
HasDuplicateAssets(const ValueObject & value)550 bool HasDuplicateAssets(const ValueObject &value)
551 {
552 auto *assets = std::get_if<ValueObject::Assets>(&value.value);
553 if (assets == nullptr) {
554 return false;
555 }
556 std::set<std::string> names;
557 auto item = assets->begin();
558 while (item != assets->end()) {
559 if (!names.insert(item->name).second) {
560 LOG_ERROR("Duplicate assets! name = %{public}.6s", item->name.c_str());
561 return true;
562 }
563 item++;
564 }
565 return false;
566 }
567
HasDuplicateAssets(const std::vector<ValueObject> & values)568 bool HasDuplicateAssets(const std::vector<ValueObject> &values)
569 {
570 for (auto &val : values) {
571 if (HasDuplicateAssets(val)) {
572 return true;
573 }
574 }
575 return false;
576 }
577
HasDuplicateAssets(const ValuesBucket & value)578 bool HasDuplicateAssets(const ValuesBucket &value)
579 {
580 for (auto &[key, val] : value.values_) {
581 if (HasDuplicateAssets(val)) {
582 return true;
583 }
584 }
585 return false;
586 }
587
HasDuplicateAssets(const std::vector<ValuesBucket> & values)588 bool HasDuplicateAssets(const std::vector<ValuesBucket> &values)
589 {
590 for (auto &valueBucket : values) {
591 if (HasDuplicateAssets(valueBucket)) {
592 return true;
593 }
594 }
595 return false;
596 }
597
HasDuplicateAssets(const ValuesBuckets & values)598 bool HasDuplicateAssets(const ValuesBuckets &values)
599 {
600 const auto &[fields, vals] = values.GetFieldsAndValues();
601 for (const auto &valueObject : *vals) {
602 if (HasDuplicateAssets(valueObject)) {
603 return true;
604 }
605 }
606 return false;
607 }
608 }; // namespace JSUtils
609 } // namespace OHOS::AppDataMgrJsKit