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_web_data_base.h"
17 
18 #include <cstdint>
19 #include <cstring>
20 #include <vector>
21 
22 #include "business_error.h"
23 #include "napi/native_common.h"
24 #include "nweb_data_base.h"
25 #include "nweb_helper.h"
26 #include "web_errors.h"
27 #include "securec.h"
28 
29 #include "nweb_log.h"
30 
31 namespace {
32 constexpr int32_t MAX_STRING_LENGTH = 40960;
33 constexpr int32_t MAX_PWD_LENGTH = 256;
34 constexpr int32_t PARAMZERO = 0;
35 constexpr int32_t PARAMONE = 1;
36 constexpr int32_t PARAMTWO = 2;
37 constexpr int32_t PARAMTHREE = 3;
38 constexpr int32_t PARAMFOUR = 4;
39 }
40 
41 namespace OHOS {
42 namespace NWeb {
Init(napi_env env,napi_value exports)43 napi_value NapiWebDataBase::Init(napi_env env, napi_value exports)
44 {
45     const std::string WEB_DATA_BASE_CLASS_NAME = "WebDataBase";
46     napi_property_descriptor properties[] = {
47         DECLARE_NAPI_STATIC_FUNCTION("deleteHttpAuthCredentials", NapiWebDataBase::JsDeleteHttpAuthCredentials),
48         DECLARE_NAPI_STATIC_FUNCTION("saveHttpAuthCredentials", NapiWebDataBase::JsSaveHttpAuthCredentials),
49         DECLARE_NAPI_STATIC_FUNCTION("getHttpAuthCredentials", NapiWebDataBase::JsGetHttpAuthCredentials),
50         DECLARE_NAPI_STATIC_FUNCTION("existHttpAuthCredentials", NapiWebDataBase::JsExistHttpAuthCredentials),
51     };
52     napi_value constructor = nullptr;
53 
54     napi_define_class(env, WEB_DATA_BASE_CLASS_NAME.c_str(), WEB_DATA_BASE_CLASS_NAME.length(), JsConstructor, nullptr,
55         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
56     NAPI_ASSERT(env, constructor != nullptr, "NapiWebDataBase define js class failed");
57     napi_status status = napi_set_named_property(env, exports, "WebDataBase", constructor);
58     NAPI_ASSERT(env, status == napi_ok, "NapiWebDataBase set property failed");
59     return exports;
60 }
61 
JsDeleteHttpAuthCredentials(napi_env env,napi_callback_info info)62 napi_value NapiWebDataBase::JsDeleteHttpAuthCredentials(napi_env env, napi_callback_info info)
63 {
64     napi_value result = nullptr;
65     std::shared_ptr<OHOS::NWeb::NWebDataBase> dataBase = OHOS::NWeb::NWebHelper::Instance().GetDataBase();
66     if (dataBase != nullptr) {
67         dataBase->DeleteHttpAuthCredentials();
68     }
69     napi_get_undefined(env, &result);
70     return result;
71 }
72 
JsExistHttpAuthCredentials(napi_env env,napi_callback_info info)73 napi_value NapiWebDataBase::JsExistHttpAuthCredentials(napi_env env, napi_callback_info info)
74 {
75     bool isExist = false;
76     napi_value result = nullptr;
77 
78     std::shared_ptr<OHOS::NWeb::NWebDataBase> dataBase = OHOS::NWeb::NWebHelper::Instance().GetDataBase();
79     if (dataBase != nullptr) {
80         isExist = dataBase->ExistHttpAuthCredentials();
81     }
82     NAPI_CALL(env, napi_get_boolean(env, isExist, &result));
83     return result;
84 }
85 
GetStringPara(napi_env env,napi_value argv,std::string & outValue)86 bool NapiWebDataBase::GetStringPara(napi_env env, napi_value argv, std::string& outValue)
87 {
88     size_t bufferSize = 0;
89     napi_valuetype valueType = napi_null;
90 
91     napi_typeof(env, argv, &valueType);
92     if (valueType != napi_string) {
93         return false;
94     }
95     napi_get_value_string_utf8(env, argv, nullptr, 0, &bufferSize);
96     if (bufferSize > MAX_STRING_LENGTH) {
97         return false;
98     }
99     char stringValue[bufferSize + 1];
100     size_t jsStringLength = 0;
101     napi_get_value_string_utf8(env, argv, stringValue, bufferSize + 1, &jsStringLength);
102     if (jsStringLength != bufferSize) {
103         return false;
104     }
105     outValue = stringValue;
106     return true;
107 }
108 
GetSize(napi_env env,napi_value argv,size_t & outValue)109 bool NapiWebDataBase::GetSize(napi_env env, napi_value argv, size_t& outValue)
110 {
111     size_t bufferSize = 0;
112     napi_valuetype valueType = napi_null;
113 
114     napi_typeof(env, argv, &valueType);
115     if (valueType != napi_string) {
116         return false;
117     }
118     napi_get_value_string_utf8(env, argv, nullptr, 0, &bufferSize);
119     if (bufferSize > MAX_STRING_LENGTH) {
120         return false;
121     }
122     outValue = bufferSize;
123     return true;
124 }
125 
GetCharPara(napi_env env,napi_value argv,char * buffer,size_t bufferSize)126 bool NapiWebDataBase::GetCharPara(napi_env env, napi_value argv, char* buffer, size_t bufferSize)
127 {
128     if (bufferSize == 0) {
129         return false;
130     }
131     size_t jsStringLength = 0;
132     napi_get_value_string_utf8(env, argv, buffer, bufferSize + 1, &jsStringLength);
133     if (jsStringLength != bufferSize) {
134         return false;
135     }
136     return true;
137 }
138 
JsSaveHttpAuthCredentials(napi_env env,napi_callback_info info)139 napi_value NapiWebDataBase::JsSaveHttpAuthCredentials(napi_env env, napi_callback_info info)
140 {
141     napi_value retValue = nullptr;
142     size_t argc = 4;
143     napi_value argv[4] = { 0 };
144     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
145     if (argc != PARAMFOUR) {
146         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
147             NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NUMBERS_ERROR_ONE, "four"));
148         return nullptr;
149     }
150     std::string host;
151     if (!GetStringPara(env, argv[PARAMZERO], host)) {
152         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
153             NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "host", "string"));
154         return nullptr;
155     }
156     std::string realm;
157     if (!GetStringPara(env, argv[PARAMONE], realm)) {
158         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
159             NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "realm", "string"));
160         return nullptr;
161     }
162     std::string username;
163     if (!GetStringPara(env, argv[PARAMTWO], username)) {
164         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
165             NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "username", "string"));
166         return nullptr;
167     }
168     if (host.empty() || username.empty()) {
169         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
170             NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NOT_NULL_TWO, "username", "string"));
171         return nullptr;
172     }
173     size_t bufferSize = 0;
174     if (!GetSize(env, argv[PARAMTHREE], bufferSize) || bufferSize > MAX_PWD_LENGTH) {
175         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
176             "BusinessError 401: Parameter error. The length of 'password' must be between 0 and 256.");
177         return nullptr;
178     }
179     if (bufferSize > 0) {
180         char password[bufferSize + 1];
181         if (!GetCharPara(env, argv[PARAMTHREE], password, bufferSize)) {
182             NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
183                 "BusinessError 401: Parameter error. The length of 'password' obtained twice are different");
184             return nullptr;
185         }
186         std::shared_ptr<OHOS::NWeb::NWebDataBase> dataBase = OHOS::NWeb::NWebHelper::Instance().GetDataBase();
187         if (dataBase != nullptr) {
188             dataBase->SaveHttpAuthCredentials(host, realm, username, password);
189         }
190         (void)memset_s(password, sizeof(password), 0, sizeof(password));
191     }
192     napi_value result = nullptr;
193     napi_get_undefined(env, &result);
194     return result;
195 }
196 
JsGetHttpAuthCredentials(napi_env env,napi_callback_info info)197 napi_value NapiWebDataBase::JsGetHttpAuthCredentials(napi_env env, napi_callback_info info)
198 {
199     napi_value retValue = nullptr;
200     size_t argc = 2;
201     napi_value argv[2] = { 0 };
202 
203     napi_get_cb_info(env, info, &argc, argv, &retValue, nullptr);
204     if (argc != PARAMTWO) {
205         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
206             NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NUMBERS_ERROR_ONE, "two"));
207         return nullptr;
208     }
209 
210     std::string host;
211     if (!GetStringPara(env, argv[PARAMZERO], host)) {
212         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
213             NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "host", "string"));
214         return nullptr;
215     }
216 
217     std::string realm;
218     if (!GetStringPara(env, argv[PARAMONE], realm)) {
219         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
220             NWebError::FormatString(ParamCheckErrorMsgTemplate::TYPE_ERROR, "realm", "string"));
221         return nullptr;
222     }
223 
224     if (host.empty()) {
225         NWebError::BusinessError::ThrowErrorByErrcode(env, NWebError::PARAM_CHECK_ERROR,
226             NWebError::FormatString(ParamCheckErrorMsgTemplate::PARAM_NOT_NULL, "host"));
227         return nullptr;
228     }
229 
230     std::string username;
231     char password[MAX_PWD_LENGTH + 1] = {0};
232     napi_value result = nullptr;
233     napi_create_array(env, &result);
234 
235     std::shared_ptr<OHOS::NWeb::NWebDataBase> dataBase = OHOS::NWeb::NWebHelper::Instance().GetDataBase();
236     if (dataBase != nullptr) {
237         dataBase->GetHttpAuthCredentials(host, realm, username, password, MAX_PWD_LENGTH + 1);
238     }
239     if (!username.empty() && strlen(password) > 0) {
240         napi_value nameVal = nullptr;
241         napi_value pwdVal = nullptr;
242         napi_create_string_utf8(env, username.c_str(), username.length(), &nameVal);
243         napi_set_element(env, result, PARAMZERO, nameVal);
244         napi_create_string_utf8(env, password, strlen(password), &pwdVal);
245         napi_set_element(env, result, PARAMONE, pwdVal);
246     }
247     (void)memset_s(password, MAX_PWD_LENGTH + 1, 0, MAX_PWD_LENGTH + 1);
248     return result;
249 }
250 
JsConstructor(napi_env env,napi_callback_info info)251 napi_value NapiWebDataBase::JsConstructor(napi_env env, napi_callback_info info)
252 {
253     napi_value thisVar = nullptr;
254     size_t argc = 2;
255     napi_value argv[2] = { 0 };
256     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
257     return thisVar;
258 }
259 } // namespace NWeb
260 } // namespace OHOS
261