10e98b08fSopenharmony_ci/*
20e98b08fSopenharmony_ci * Copyright (c) 2020 Huawei Device Co., Ltd.
30e98b08fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
40e98b08fSopenharmony_ci * you may not use this file except in compliance with the License.
50e98b08fSopenharmony_ci * You may obtain a copy of the License at
60e98b08fSopenharmony_ci *
70e98b08fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
80e98b08fSopenharmony_ci *
90e98b08fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
100e98b08fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
110e98b08fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120e98b08fSopenharmony_ci * See the License for the specific language governing permissions and
130e98b08fSopenharmony_ci * limitations under the License.
140e98b08fSopenharmony_ci */
150e98b08fSopenharmony_ci
160e98b08fSopenharmony_ci#include "nativeapi_kv.h"
170e98b08fSopenharmony_ci#include <securec.h>
180e98b08fSopenharmony_ci#include <new>
190e98b08fSopenharmony_ci#include "ability_env.h"
200e98b08fSopenharmony_ci#include "js_async_work.h"
210e98b08fSopenharmony_ci#include "nativeapi_common.h"
220e98b08fSopenharmony_ci#include "nativeapi_config.h"
230e98b08fSopenharmony_ci#include "nativeapi_kv_impl.h"
240e98b08fSopenharmony_ci
250e98b08fSopenharmony_cinamespace OHOS {
260e98b08fSopenharmony_cinamespace ACELite {
270e98b08fSopenharmony_cinamespace {
280e98b08fSopenharmony_cichar g_kvFullPath[FILE_NAME_MAX_LEN + 1] = {0};
290e98b08fSopenharmony_ci
300e98b08fSopenharmony_cibool IsValidKey(const char* key)
310e98b08fSopenharmony_ci{
320e98b08fSopenharmony_ci    if (key == nullptr) {
330e98b08fSopenharmony_ci        return false;
340e98b08fSopenharmony_ci    }
350e98b08fSopenharmony_ci    size_t keyLen = strnlen(key, KEY_MAX_LEN + 1);
360e98b08fSopenharmony_ci    if ((keyLen == 0) || (keyLen > KEY_MAX_LEN)) {
370e98b08fSopenharmony_ci        return false;
380e98b08fSopenharmony_ci    }
390e98b08fSopenharmony_ci    if (strpbrk(key, "/\\\"*+,:;<=>\?[]|\x7F")) {
400e98b08fSopenharmony_ci        return false;
410e98b08fSopenharmony_ci    }
420e98b08fSopenharmony_ci    return true;
430e98b08fSopenharmony_ci}
440e98b08fSopenharmony_ci
450e98b08fSopenharmony_ciint GetFullPath(const char* dataPath, const char* key)
460e98b08fSopenharmony_ci{
470e98b08fSopenharmony_ci    if (!IsValidKey(key) || (dataPath == nullptr)) {
480e98b08fSopenharmony_ci        return ERROR_CODE_PARAM;
490e98b08fSopenharmony_ci    }
500e98b08fSopenharmony_ci    if (memset_s(g_kvFullPath, sizeof(g_kvFullPath), 0x0, sizeof(g_kvFullPath)) != EOK) {
510e98b08fSopenharmony_ci        return ERROR_CODE_GENERAL;
520e98b08fSopenharmony_ci    }
530e98b08fSopenharmony_ci    if (sprintf_s(g_kvFullPath, sizeof(g_kvFullPath), "%s/%s/%s", dataPath, DEFAULT_FOLDER_PATH, key) < 0) {
540e98b08fSopenharmony_ci        return ERROR_CODE_GENERAL;
550e98b08fSopenharmony_ci    }
560e98b08fSopenharmony_ci    return NATIVE_SUCCESS;
570e98b08fSopenharmony_ci}
580e98b08fSopenharmony_ci
590e98b08fSopenharmony_civoid GetDefault(const JSIValue thisVal, const JSIValue args)
600e98b08fSopenharmony_ci{
610e98b08fSopenharmony_ci    char* defaultValue = JSI::GetStringProperty(args, DEFAULT);
620e98b08fSopenharmony_ci    JSIValue result;
630e98b08fSopenharmony_ci    if (defaultValue == nullptr) {
640e98b08fSopenharmony_ci        result = JSI::CreateString("");
650e98b08fSopenharmony_ci    } else {
660e98b08fSopenharmony_ci        result = JSI::CreateString(defaultValue);
670e98b08fSopenharmony_ci    }
680e98b08fSopenharmony_ci    JSI::ReleaseString(defaultValue);
690e98b08fSopenharmony_ci    NativeapiCommon::SuccessCallBack(thisVal, args, result);
700e98b08fSopenharmony_ci    JSI::ReleaseValue(result);
710e98b08fSopenharmony_ci}
720e98b08fSopenharmony_ci
730e98b08fSopenharmony_ciint GetValueInner(const char* dataPath, const char* key, char* value)
740e98b08fSopenharmony_ci{
750e98b08fSopenharmony_ci    int ret = GetFullPath(dataPath, key);
760e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
770e98b08fSopenharmony_ci        return ret;
780e98b08fSopenharmony_ci    }
790e98b08fSopenharmony_ci    return GetValue(g_kvFullPath, value);
800e98b08fSopenharmony_ci}
810e98b08fSopenharmony_ci
820e98b08fSopenharmony_ciint SetValueInner(const char* dataPath, const char* key, const char* value)
830e98b08fSopenharmony_ci{
840e98b08fSopenharmony_ci    int ret = GetFullPath(dataPath, key);
850e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
860e98b08fSopenharmony_ci        return ret;
870e98b08fSopenharmony_ci    }
880e98b08fSopenharmony_ci    return SetValue(g_kvFullPath, value);
890e98b08fSopenharmony_ci}
900e98b08fSopenharmony_ci
910e98b08fSopenharmony_ciint DeleteValueInner(const char* dataPath, const char* key)
920e98b08fSopenharmony_ci{
930e98b08fSopenharmony_ci    int ret = GetFullPath(dataPath, key);
940e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
950e98b08fSopenharmony_ci        return ret;
960e98b08fSopenharmony_ci    }
970e98b08fSopenharmony_ci    return DeleteValue(g_kvFullPath);
980e98b08fSopenharmony_ci}
990e98b08fSopenharmony_ci
1000e98b08fSopenharmony_ciJSIValue ExecuteAsyncWork(const JSIValue thisVal, const JSIValue* args,
1010e98b08fSopenharmony_ci    uint8_t argsNum, AsyncWorkHandler ExecuteFunc, bool flag)
1020e98b08fSopenharmony_ci{
1030e98b08fSopenharmony_ci    JSIValue undefValue = JSI::CreateUndefined();
1040e98b08fSopenharmony_ci    if (!NativeapiCommon::IsValidJSIValue(args, argsNum)) {
1050e98b08fSopenharmony_ci        return undefValue;
1060e98b08fSopenharmony_ci    }
1070e98b08fSopenharmony_ci    FuncParams* params = new(std::nothrow) FuncParams();
1080e98b08fSopenharmony_ci    if (params == nullptr) {
1090e98b08fSopenharmony_ci        return undefValue;
1100e98b08fSopenharmony_ci    }
1110e98b08fSopenharmony_ci    params->thisVal = JSI::AcquireValue(thisVal);
1120e98b08fSopenharmony_ci    params->args = JSI::AcquireValue(args[0]);
1130e98b08fSopenharmony_ci    params->flag = flag;
1140e98b08fSopenharmony_ci    JsAsyncWork::DispatchAsyncWork(ExecuteFunc, reinterpret_cast<void *>(params));
1150e98b08fSopenharmony_ci    return undefValue;
1160e98b08fSopenharmony_ci}
1170e98b08fSopenharmony_ci
1180e98b08fSopenharmony_civoid ExecuteGet(void* data)
1190e98b08fSopenharmony_ci{
1200e98b08fSopenharmony_ci    FuncParams* params = reinterpret_cast<FuncParams *>(data);
1210e98b08fSopenharmony_ci    if (params == nullptr) {
1220e98b08fSopenharmony_ci        return;
1230e98b08fSopenharmony_ci    }
1240e98b08fSopenharmony_ci    JSIValue args = params->args;
1250e98b08fSopenharmony_ci    JSIValue thisVal = params->thisVal;
1260e98b08fSopenharmony_ci    char* key = JSI::GetStringProperty(args, KV_KEY);
1270e98b08fSopenharmony_ci    const char* dataPath = GetDataPath();
1280e98b08fSopenharmony_ci    JSIValue result = JSI::CreateUndefined();
1290e98b08fSopenharmony_ci    int ret = ERROR_CODE_GENERAL;
1300e98b08fSopenharmony_ci    char* value = reinterpret_cast<char *>(malloc(VALUE_MAX_LEN + 1));
1310e98b08fSopenharmony_ci    if (value == nullptr) {
1320e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
1330e98b08fSopenharmony_ci        goto EXIT;
1340e98b08fSopenharmony_ci    }
1350e98b08fSopenharmony_ci    ret = InitKv(dataPath);
1360e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
1370e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
1380e98b08fSopenharmony_ci        goto EXIT;
1390e98b08fSopenharmony_ci    }
1400e98b08fSopenharmony_ci    ret = GetValueInner(dataPath, key, value);
1410e98b08fSopenharmony_ci    if (ret == ERROR_FR_NO_FILE) {
1420e98b08fSopenharmony_ci        GetDefault(thisVal, args);
1430e98b08fSopenharmony_ci        goto EXIT;
1440e98b08fSopenharmony_ci    }
1450e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
1460e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
1470e98b08fSopenharmony_ci        goto EXIT;
1480e98b08fSopenharmony_ci    }
1490e98b08fSopenharmony_ci    result = JSI::CreateString(value);
1500e98b08fSopenharmony_ci    NativeapiCommon::SuccessCallBack(thisVal, args, result);
1510e98b08fSopenharmony_ciEXIT:
1520e98b08fSopenharmony_ci    free(value);
1530e98b08fSopenharmony_ci    JSI::ReleaseString(key);
1540e98b08fSopenharmony_ci    JSI::ReleaseValueList(args, thisVal, result, ARGS_END);
1550e98b08fSopenharmony_ci    delete params;
1560e98b08fSopenharmony_ci}
1570e98b08fSopenharmony_ci
1580e98b08fSopenharmony_civoid ExecuteSet(void* data)
1590e98b08fSopenharmony_ci{
1600e98b08fSopenharmony_ci    FuncParams* params = reinterpret_cast<FuncParams *>(data);
1610e98b08fSopenharmony_ci    if (params == nullptr) {
1620e98b08fSopenharmony_ci        return;
1630e98b08fSopenharmony_ci    }
1640e98b08fSopenharmony_ci    JSIValue args = params->args;
1650e98b08fSopenharmony_ci    JSIValue thisVal = params->thisVal;
1660e98b08fSopenharmony_ci    char* key = JSI::GetStringProperty(args, KV_KEY);
1670e98b08fSopenharmony_ci    char* value = JSI::GetStringProperty(args, KV_VALUE);
1680e98b08fSopenharmony_ci    const char* dataPath = GetDataPath();
1690e98b08fSopenharmony_ci    int ret = InitKv(dataPath);
1700e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
1710e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
1720e98b08fSopenharmony_ci        goto EXIT;
1730e98b08fSopenharmony_ci    }
1740e98b08fSopenharmony_ci    if ((key == nullptr) || !strlen(key)) {
1750e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ERROR_CODE_PARAM);
1760e98b08fSopenharmony_ci        goto EXIT;
1770e98b08fSopenharmony_ci    }
1780e98b08fSopenharmony_ci    if ((value == nullptr) || !strlen(value)) {
1790e98b08fSopenharmony_ci        DeleteValueInner(dataPath, key);
1800e98b08fSopenharmony_ci        NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
1810e98b08fSopenharmony_ci        goto EXIT;
1820e98b08fSopenharmony_ci    }
1830e98b08fSopenharmony_ci    ret = SetValueInner(dataPath, key, value);
1840e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
1850e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
1860e98b08fSopenharmony_ci        goto EXIT;
1870e98b08fSopenharmony_ci    }
1880e98b08fSopenharmony_ci    NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
1890e98b08fSopenharmony_ciEXIT:
1900e98b08fSopenharmony_ci    JSI::ReleaseString(key);
1910e98b08fSopenharmony_ci    JSI::ReleaseString(value);
1920e98b08fSopenharmony_ci    JSI::ReleaseValueList(args, thisVal, ARGS_END);
1930e98b08fSopenharmony_ci    delete params;
1940e98b08fSopenharmony_ci}
1950e98b08fSopenharmony_ci
1960e98b08fSopenharmony_civoid ExecuteDelete(void* data)
1970e98b08fSopenharmony_ci{
1980e98b08fSopenharmony_ci    FuncParams* params = reinterpret_cast<FuncParams *>(data);
1990e98b08fSopenharmony_ci    if (params == nullptr) {
2000e98b08fSopenharmony_ci        return;
2010e98b08fSopenharmony_ci    }
2020e98b08fSopenharmony_ci    JSIValue args = params->args;
2030e98b08fSopenharmony_ci    JSIValue thisVal = params->thisVal;
2040e98b08fSopenharmony_ci    const char* dataPath = GetDataPath();
2050e98b08fSopenharmony_ci    int ret = InitKv(dataPath);
2060e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
2070e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
2080e98b08fSopenharmony_ci        JSI::ReleaseValueList(args, thisVal, ARGS_END);
2090e98b08fSopenharmony_ci        delete params;
2100e98b08fSopenharmony_ci        return;
2110e98b08fSopenharmony_ci    }
2120e98b08fSopenharmony_ci    char* key = JSI::GetStringProperty(args, KV_KEY);
2130e98b08fSopenharmony_ci    ret = DeleteValueInner(dataPath, key);
2140e98b08fSopenharmony_ci    JSI::ReleaseString(key);
2150e98b08fSopenharmony_ci    if ((ret < 0) && (ret != ERROR_FR_NO_FILE)) {
2160e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
2170e98b08fSopenharmony_ci        JSI::ReleaseValueList(args, thisVal, ARGS_END);
2180e98b08fSopenharmony_ci        delete params;
2190e98b08fSopenharmony_ci        return;
2200e98b08fSopenharmony_ci    }
2210e98b08fSopenharmony_ci    NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
2220e98b08fSopenharmony_ci    JSI::ReleaseValueList(args, thisVal, ARGS_END);
2230e98b08fSopenharmony_ci    delete params;
2240e98b08fSopenharmony_ci}
2250e98b08fSopenharmony_ci
2260e98b08fSopenharmony_civoid ExecuteClear(void* data)
2270e98b08fSopenharmony_ci{
2280e98b08fSopenharmony_ci    FuncParams* params = reinterpret_cast<FuncParams *>(data);
2290e98b08fSopenharmony_ci    if (params == nullptr) {
2300e98b08fSopenharmony_ci        return;
2310e98b08fSopenharmony_ci    }
2320e98b08fSopenharmony_ci    JSIValue args = params->args;
2330e98b08fSopenharmony_ci    JSIValue thisVal = params->thisVal;
2340e98b08fSopenharmony_ci    const char* dataPath = GetDataPath();
2350e98b08fSopenharmony_ci    int ret = InitKv(dataPath);
2360e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
2370e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
2380e98b08fSopenharmony_ci        JSI::ReleaseValueList(args, thisVal, ARGS_END);
2390e98b08fSopenharmony_ci        delete params;
2400e98b08fSopenharmony_ci        return;
2410e98b08fSopenharmony_ci    }
2420e98b08fSopenharmony_ci    ret = ClearKVStore(dataPath);
2430e98b08fSopenharmony_ci    if (ret != NATIVE_SUCCESS) {
2440e98b08fSopenharmony_ci        NativeapiCommon::FailCallBack(thisVal, args, ret);
2450e98b08fSopenharmony_ci        JSI::ReleaseValueList(args, thisVal, ARGS_END);
2460e98b08fSopenharmony_ci        delete params;
2470e98b08fSopenharmony_ci        return;
2480e98b08fSopenharmony_ci    }
2490e98b08fSopenharmony_ci    NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
2500e98b08fSopenharmony_ci    JSI::ReleaseValueList(args, thisVal, ARGS_END);
2510e98b08fSopenharmony_ci    delete params;
2520e98b08fSopenharmony_ci}
2530e98b08fSopenharmony_ci}
2540e98b08fSopenharmony_ci
2550e98b08fSopenharmony_civoid InitNativeApiKv(JSIValue exports)
2560e98b08fSopenharmony_ci{
2570e98b08fSopenharmony_ci    JSI::SetModuleAPI(exports, "get", NativeapiKv::Get);
2580e98b08fSopenharmony_ci    JSI::SetModuleAPI(exports, "set", NativeapiKv::Set);
2590e98b08fSopenharmony_ci    JSI::SetModuleAPI(exports, "delete", NativeapiKv::Delete);
2600e98b08fSopenharmony_ci    JSI::SetModuleAPI(exports, "clear", NativeapiKv::Clear);
2610e98b08fSopenharmony_ci}
2620e98b08fSopenharmony_ci
2630e98b08fSopenharmony_ciJSIValue NativeapiKv::Get(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
2640e98b08fSopenharmony_ci{
2650e98b08fSopenharmony_ci    return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteGet, false);
2660e98b08fSopenharmony_ci}
2670e98b08fSopenharmony_ci
2680e98b08fSopenharmony_ciJSIValue NativeapiKv::Set(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
2690e98b08fSopenharmony_ci{
2700e98b08fSopenharmony_ci    return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteSet, false);
2710e98b08fSopenharmony_ci}
2720e98b08fSopenharmony_ci
2730e98b08fSopenharmony_ciJSIValue NativeapiKv::Delete(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
2740e98b08fSopenharmony_ci{
2750e98b08fSopenharmony_ci    return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteDelete, false);
2760e98b08fSopenharmony_ci}
2770e98b08fSopenharmony_ci
2780e98b08fSopenharmony_ciJSIValue NativeapiKv::Clear(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
2790e98b08fSopenharmony_ci{
2800e98b08fSopenharmony_ci    JSIValue undefValue = JSI::CreateUndefined();
2810e98b08fSopenharmony_ci    FuncParams* params = new(std::nothrow) FuncParams();
2820e98b08fSopenharmony_ci    if (params == nullptr) {
2830e98b08fSopenharmony_ci        return undefValue;
2840e98b08fSopenharmony_ci    }
2850e98b08fSopenharmony_ci    params->thisVal = JSI::AcquireValue(thisVal);
2860e98b08fSopenharmony_ci    if (NativeapiCommon::IsValidJSIValue(args, argsNum)) {
2870e98b08fSopenharmony_ci        params->args = JSI::AcquireValue(args[0]);
2880e98b08fSopenharmony_ci    }
2890e98b08fSopenharmony_ci    JsAsyncWork::DispatchAsyncWork(reinterpret_cast<AsyncWorkHandler>(ExecuteClear), reinterpret_cast<void *>(params));
2900e98b08fSopenharmony_ci    return undefValue;
2910e98b08fSopenharmony_ci}
2920e98b08fSopenharmony_ci} // ACELite
2930e98b08fSopenharmony_ci} // OHOS
294