1 /*
2  * Copyright (c) 2020 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 "nativeapi_kv.h"
17 #include <securec.h>
18 #include <new>
19 #include "ability_env.h"
20 #include "js_async_work.h"
21 #include "nativeapi_common.h"
22 #include "nativeapi_config.h"
23 #include "nativeapi_kv_impl.h"
24 
25 namespace OHOS {
26 namespace ACELite {
27 namespace {
28 char g_kvFullPath[FILE_NAME_MAX_LEN + 1] = {0};
29 
IsValidKey(const char * key)30 bool IsValidKey(const char* key)
31 {
32     if (key == nullptr) {
33         return false;
34     }
35     size_t keyLen = strnlen(key, KEY_MAX_LEN + 1);
36     if ((keyLen == 0) || (keyLen > KEY_MAX_LEN)) {
37         return false;
38     }
39     if (strpbrk(key, "/\\\"*+,:;<=>\?[]|\x7F")) {
40         return false;
41     }
42     return true;
43 }
44 
GetFullPath(const char * dataPath,const char * key)45 int GetFullPath(const char* dataPath, const char* key)
46 {
47     if (!IsValidKey(key) || (dataPath == nullptr)) {
48         return ERROR_CODE_PARAM;
49     }
50     if (memset_s(g_kvFullPath, sizeof(g_kvFullPath), 0x0, sizeof(g_kvFullPath)) != EOK) {
51         return ERROR_CODE_GENERAL;
52     }
53     if (sprintf_s(g_kvFullPath, sizeof(g_kvFullPath), "%s/%s/%s", dataPath, DEFAULT_FOLDER_PATH, key) < 0) {
54         return ERROR_CODE_GENERAL;
55     }
56     return NATIVE_SUCCESS;
57 }
58 
GetDefault(const JSIValue thisVal,const JSIValue args)59 void GetDefault(const JSIValue thisVal, const JSIValue args)
60 {
61     char* defaultValue = JSI::GetStringProperty(args, DEFAULT);
62     JSIValue result;
63     if (defaultValue == nullptr) {
64         result = JSI::CreateString("");
65     } else {
66         result = JSI::CreateString(defaultValue);
67     }
68     JSI::ReleaseString(defaultValue);
69     NativeapiCommon::SuccessCallBack(thisVal, args, result);
70     JSI::ReleaseValue(result);
71 }
72 
GetValueInner(const char * dataPath,const char * key,char * value)73 int GetValueInner(const char* dataPath, const char* key, char* value)
74 {
75     int ret = GetFullPath(dataPath, key);
76     if (ret != NATIVE_SUCCESS) {
77         return ret;
78     }
79     return GetValue(g_kvFullPath, value);
80 }
81 
SetValueInner(const char * dataPath,const char * key,const char * value)82 int SetValueInner(const char* dataPath, const char* key, const char* value)
83 {
84     int ret = GetFullPath(dataPath, key);
85     if (ret != NATIVE_SUCCESS) {
86         return ret;
87     }
88     return SetValue(g_kvFullPath, value);
89 }
90 
DeleteValueInner(const char * dataPath,const char * key)91 int DeleteValueInner(const char* dataPath, const char* key)
92 {
93     int ret = GetFullPath(dataPath, key);
94     if (ret != NATIVE_SUCCESS) {
95         return ret;
96     }
97     return DeleteValue(g_kvFullPath);
98 }
99 
ExecuteAsyncWork(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum,AsyncWorkHandler ExecuteFunc,bool flag)100 JSIValue ExecuteAsyncWork(const JSIValue thisVal, const JSIValue* args,
101     uint8_t argsNum, AsyncWorkHandler ExecuteFunc, bool flag)
102 {
103     JSIValue undefValue = JSI::CreateUndefined();
104     if (!NativeapiCommon::IsValidJSIValue(args, argsNum)) {
105         return undefValue;
106     }
107     FuncParams* params = new(std::nothrow) FuncParams();
108     if (params == nullptr) {
109         return undefValue;
110     }
111     params->thisVal = JSI::AcquireValue(thisVal);
112     params->args = JSI::AcquireValue(args[0]);
113     params->flag = flag;
114     JsAsyncWork::DispatchAsyncWork(ExecuteFunc, reinterpret_cast<void *>(params));
115     return undefValue;
116 }
117 
ExecuteGet(void * data)118 void ExecuteGet(void* data)
119 {
120     FuncParams* params = reinterpret_cast<FuncParams *>(data);
121     if (params == nullptr) {
122         return;
123     }
124     JSIValue args = params->args;
125     JSIValue thisVal = params->thisVal;
126     char* key = JSI::GetStringProperty(args, KV_KEY);
127     const char* dataPath = GetDataPath();
128     JSIValue result = JSI::CreateUndefined();
129     int ret = ERROR_CODE_GENERAL;
130     char* value = reinterpret_cast<char *>(malloc(VALUE_MAX_LEN + 1));
131     if (value == nullptr) {
132         NativeapiCommon::FailCallBack(thisVal, args, ret);
133         goto EXIT;
134     }
135     ret = InitKv(dataPath);
136     if (ret != NATIVE_SUCCESS) {
137         NativeapiCommon::FailCallBack(thisVal, args, ret);
138         goto EXIT;
139     }
140     ret = GetValueInner(dataPath, key, value);
141     if (ret == ERROR_FR_NO_FILE) {
142         GetDefault(thisVal, args);
143         goto EXIT;
144     }
145     if (ret != NATIVE_SUCCESS) {
146         NativeapiCommon::FailCallBack(thisVal, args, ret);
147         goto EXIT;
148     }
149     result = JSI::CreateString(value);
150     NativeapiCommon::SuccessCallBack(thisVal, args, result);
151 EXIT:
152     free(value);
153     JSI::ReleaseString(key);
154     JSI::ReleaseValueList(args, thisVal, result, ARGS_END);
155     delete params;
156 }
157 
ExecuteSet(void * data)158 void ExecuteSet(void* data)
159 {
160     FuncParams* params = reinterpret_cast<FuncParams *>(data);
161     if (params == nullptr) {
162         return;
163     }
164     JSIValue args = params->args;
165     JSIValue thisVal = params->thisVal;
166     char* key = JSI::GetStringProperty(args, KV_KEY);
167     char* value = JSI::GetStringProperty(args, KV_VALUE);
168     const char* dataPath = GetDataPath();
169     int ret = InitKv(dataPath);
170     if (ret != NATIVE_SUCCESS) {
171         NativeapiCommon::FailCallBack(thisVal, args, ret);
172         goto EXIT;
173     }
174     if ((key == nullptr) || !strlen(key)) {
175         NativeapiCommon::FailCallBack(thisVal, args, ERROR_CODE_PARAM);
176         goto EXIT;
177     }
178     if ((value == nullptr) || !strlen(value)) {
179         DeleteValueInner(dataPath, key);
180         NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
181         goto EXIT;
182     }
183     ret = SetValueInner(dataPath, key, value);
184     if (ret != NATIVE_SUCCESS) {
185         NativeapiCommon::FailCallBack(thisVal, args, ret);
186         goto EXIT;
187     }
188     NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
189 EXIT:
190     JSI::ReleaseString(key);
191     JSI::ReleaseString(value);
192     JSI::ReleaseValueList(args, thisVal, ARGS_END);
193     delete params;
194 }
195 
ExecuteDelete(void * data)196 void ExecuteDelete(void* data)
197 {
198     FuncParams* params = reinterpret_cast<FuncParams *>(data);
199     if (params == nullptr) {
200         return;
201     }
202     JSIValue args = params->args;
203     JSIValue thisVal = params->thisVal;
204     const char* dataPath = GetDataPath();
205     int ret = InitKv(dataPath);
206     if (ret != NATIVE_SUCCESS) {
207         NativeapiCommon::FailCallBack(thisVal, args, ret);
208         JSI::ReleaseValueList(args, thisVal, ARGS_END);
209         delete params;
210         return;
211     }
212     char* key = JSI::GetStringProperty(args, KV_KEY);
213     ret = DeleteValueInner(dataPath, key);
214     JSI::ReleaseString(key);
215     if ((ret < 0) && (ret != ERROR_FR_NO_FILE)) {
216         NativeapiCommon::FailCallBack(thisVal, args, ret);
217         JSI::ReleaseValueList(args, thisVal, ARGS_END);
218         delete params;
219         return;
220     }
221     NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
222     JSI::ReleaseValueList(args, thisVal, ARGS_END);
223     delete params;
224 }
225 
ExecuteClear(void * data)226 void ExecuteClear(void* data)
227 {
228     FuncParams* params = reinterpret_cast<FuncParams *>(data);
229     if (params == nullptr) {
230         return;
231     }
232     JSIValue args = params->args;
233     JSIValue thisVal = params->thisVal;
234     const char* dataPath = GetDataPath();
235     int ret = InitKv(dataPath);
236     if (ret != NATIVE_SUCCESS) {
237         NativeapiCommon::FailCallBack(thisVal, args, ret);
238         JSI::ReleaseValueList(args, thisVal, ARGS_END);
239         delete params;
240         return;
241     }
242     ret = ClearKVStore(dataPath);
243     if (ret != NATIVE_SUCCESS) {
244         NativeapiCommon::FailCallBack(thisVal, args, ret);
245         JSI::ReleaseValueList(args, thisVal, ARGS_END);
246         delete params;
247         return;
248     }
249     NativeapiCommon::SuccessCallBack(thisVal, args, JSI::CreateUndefined());
250     JSI::ReleaseValueList(args, thisVal, ARGS_END);
251     delete params;
252 }
253 }
254 
InitNativeApiKv(JSIValue exports)255 void InitNativeApiKv(JSIValue exports)
256 {
257     JSI::SetModuleAPI(exports, "get", NativeapiKv::Get);
258     JSI::SetModuleAPI(exports, "set", NativeapiKv::Set);
259     JSI::SetModuleAPI(exports, "delete", NativeapiKv::Delete);
260     JSI::SetModuleAPI(exports, "clear", NativeapiKv::Clear);
261 }
262 
Get(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)263 JSIValue NativeapiKv::Get(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
264 {
265     return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteGet, false);
266 }
267 
Set(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)268 JSIValue NativeapiKv::Set(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
269 {
270     return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteSet, false);
271 }
272 
Delete(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)273 JSIValue NativeapiKv::Delete(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
274 {
275     return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteDelete, false);
276 }
277 
Clear(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)278 JSIValue NativeapiKv::Clear(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
279 {
280     JSIValue undefValue = JSI::CreateUndefined();
281     FuncParams* params = new(std::nothrow) FuncParams();
282     if (params == nullptr) {
283         return undefValue;
284     }
285     params->thisVal = JSI::AcquireValue(thisVal);
286     if (NativeapiCommon::IsValidJSIValue(args, argsNum)) {
287         params->args = JSI::AcquireValue(args[0]);
288     }
289     JsAsyncWork::DispatchAsyncWork(reinterpret_cast<AsyncWorkHandler>(ExecuteClear), reinterpret_cast<void *>(params));
290     return undefValue;
291 }
292 } // ACELite
293 } // OHOS
294