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
16 #include "napi_utils.h"
17
18 #include <fcntl.h>
19
20 #include <cstdint>
21 #include <cstring>
22 #include <fstream>
23 #include <initializer_list>
24 #include <memory>
25 #include <regex>
26
27 #include "constant.h"
28 #include "log.h"
29 #include "request_common.h"
30 #include "request_common_utils.h"
31 #include "request_manager.h"
32 #include "securec.h"
33
34 namespace OHOS::Request::NapiUtils {
35 static constexpr int64_t JS_NUMBER_MAX_VALUE = (1LL << 53) - 1;
36 static constexpr const char *NOT_SYSTEM_APP = "permission verification failed, application which is not a system "
37 "application uses system API";
38
39 static const std::map<ExceptionErrorCode, std::string> ErrorCodeToMsg{ { E_OK, E_OK_INFO },
40 { E_PERMISSION, E_PERMISSION_INFO }, { E_PARAMETER_CHECK, E_PARAMETER_CHECK_INFO },
41 { E_UNSUPPORTED, E_UNSUPPORTED_INFO }, { E_FILE_IO, E_FILE_IO_INFO }, { E_FILE_PATH, E_FILE_PATH_INFO },
42 { E_SERVICE_ERROR, E_SERVICE_ERROR_INFO }, { E_TASK_QUEUE, E_TASK_QUEUE_INFO }, { E_TASK_MODE, E_TASK_MODE_INFO },
43 { E_TASK_NOT_FOUND, E_TASK_NOT_FOUND_INFO }, { E_TASK_STATE, E_TASK_STATE_INFO }, { E_OTHER, E_OTHER_INFO },
44 { E_NOT_SYSTEM_APP, NOT_SYSTEM_APP }, { E_GROUP_NOT_FOUND, E_GROUP_NOT_FOUND_INFO } };
45
Convert2JSValue(napi_env env,const DownloadInfo & in,napi_value & out)46 napi_status Convert2JSValue(napi_env env, const DownloadInfo &in, napi_value &out)
47 {
48 napi_create_object(env, &out);
49 SetStringPropertyUtf8(env, out, "description", in.description);
50 SetUint32Property(env, out, "downloadedBytes", in.downloadedBytes);
51 SetUint32Property(env, out, "downloadId", in.downloadId);
52 SetUint32Property(env, out, "failedReason", in.failedReason);
53 SetStringPropertyUtf8(env, out, "fileName", in.fileName);
54 SetStringPropertyUtf8(env, out, "filePath", in.filePath);
55 SetUint32Property(env, out, "pausedReason", in.pausedReason);
56 SetUint32Property(env, out, "status", in.status);
57 SetStringPropertyUtf8(env, out, "targetURI", in.url);
58 SetStringPropertyUtf8(env, out, "downloadTitle", in.downloadTitle);
59 SetInt64Property(env, out, "downloadTotalBytes", in.downloadTotalBytes);
60 return napi_ok;
61 }
62
Convert2JSValue(napi_env env,std::string & in,napi_value & out)63 napi_status Convert2JSValue(napi_env env, std::string &in, napi_value &out)
64 {
65 return napi_create_string_utf8(env, in.c_str(), strlen(in.c_str()), &out);
66 }
67
Convert2JSValue(napi_env env,bool in,napi_value & out)68 napi_status Convert2JSValue(napi_env env, bool in, napi_value &out)
69 {
70 return napi_get_boolean(env, in, &out);
71 }
72
Convert2JSValue(napi_env env,bool code)73 napi_value Convert2JSValue(napi_env env, bool code)
74 {
75 napi_value value = nullptr;
76 if (napi_get_boolean(env, code, &value) != napi_ok) {
77 return nullptr;
78 }
79 return value;
80 }
81
Convert2JSValue(napi_env env,int32_t code)82 napi_value Convert2JSValue(napi_env env, int32_t code)
83 {
84 napi_value value = nullptr;
85 if (napi_create_int32(env, code, &value) != napi_ok) {
86 return nullptr;
87 }
88 return value;
89 }
90
Convert2JSValue(napi_env env,uint32_t code)91 napi_value Convert2JSValue(napi_env env, uint32_t code)
92 {
93 napi_value value = nullptr;
94 if (napi_create_uint32(env, code, &value) != napi_ok) {
95 return nullptr;
96 }
97 return value;
98 }
99
Convert2JSValue(napi_env env,int64_t code)100 napi_value Convert2JSValue(napi_env env, int64_t code)
101 {
102 napi_value value = nullptr;
103 if (napi_create_int64(env, code, &value) != napi_ok) {
104 return nullptr;
105 }
106 return value;
107 }
108
Convert2JSValue(napi_env env,uint64_t code)109 napi_value Convert2JSValue(napi_env env, uint64_t code)
110 {
111 if (code > JS_NUMBER_MAX_VALUE) {
112 return nullptr;
113 }
114 napi_value value = nullptr;
115 if (napi_create_int64(env, static_cast<int64_t>(code), &value) != napi_ok) {
116 return nullptr;
117 }
118 return value;
119 }
120
Convert2JSValue(napi_env env,const std::vector<int64_t> & code)121 napi_value Convert2JSValue(napi_env env, const std::vector<int64_t> &code)
122 {
123 napi_value value = nullptr;
124 napi_create_array_with_length(env, code.size(), &value);
125 int index = 0;
126 for (const auto &cInt : code) {
127 napi_value jsInt = Convert2JSValue(env, cInt);
128 napi_set_element(env, value, index++, jsInt);
129 }
130 return value;
131 }
132
Convert2JSValue(napi_env env,const std::vector<int32_t> & code)133 napi_value Convert2JSValue(napi_env env, const std::vector<int32_t> &code)
134 {
135 napi_value value = nullptr;
136 napi_create_array_with_length(env, code.size(), &value);
137 int index = 0;
138 for (const auto &cInt : code) {
139 napi_set_element(env, value, index++, Convert2JSValue(env, cInt));
140 }
141 return value;
142 }
143
Convert2JSValue(napi_env env,const std::vector<std::string> & ids)144 napi_value Convert2JSValue(napi_env env, const std::vector<std::string> &ids)
145 {
146 napi_value value = nullptr;
147 napi_create_array_with_length(env, ids.size(), &value);
148 int index = 0;
149 for (const auto &id : ids) {
150 napi_set_element(env, value, index++, Convert2JSValue(env, id));
151 }
152 return value;
153 }
154
Convert2JSHeadersAndBody(napi_env env,const std::map<std::string,std::string> & header,const std::vector<uint8_t> & bodyBytes,bool isSeparate)155 napi_value Convert2JSHeadersAndBody(napi_env env, const std::map<std::string, std::string> &header,
156 const std::vector<uint8_t> &bodyBytes, bool isSeparate)
157 {
158 napi_value headers = nullptr;
159 napi_create_object(env, &headers);
160 for (const auto &cInt : header) {
161 napi_set_named_property(env, headers, cInt.first.c_str(), Convert2JSValue(env, cInt.second));
162 }
163 napi_value body = nullptr;
164 if (Utf8Utils::RunUtf8Validation(bodyBytes)) {
165 napi_create_string_utf8(env, reinterpret_cast<const char *>(bodyBytes.data()), bodyBytes.size(), &body);
166 } else {
167 uint8_t *data = nullptr;
168 napi_create_arraybuffer(env, bodyBytes.size(), reinterpret_cast<void **>(&data), &body);
169 if (memcpy_s(data, bodyBytes.size(), bodyBytes.data(), bodyBytes.size()) != EOK) {
170 if (bodyBytes.size() > 0) {
171 REQUEST_HILOGW("Body data memcpy_s error");
172 }
173 }
174 }
175
176 if (isSeparate) {
177 napi_value object = nullptr;
178 napi_create_object(env, &object);
179 napi_set_named_property(env, object, "headers", headers);
180 napi_set_named_property(env, object, "body", body);
181 return object;
182 } else {
183 napi_set_named_property(env, headers, "body", body);
184 return headers;
185 }
186 }
187
Convert2JSValue(napi_env env,const std::map<std::string,std::string> & code)188 napi_value Convert2JSValue(napi_env env, const std::map<std::string, std::string> &code)
189 {
190 napi_value object = nullptr;
191 napi_create_object(env, &object);
192 for (const auto &cInt : code) {
193 napi_set_named_property(env, object, cInt.first.c_str(), Convert2JSValue(env, cInt.second));
194 }
195 return object;
196 }
197
Convert2JSValue(napi_env env,const std::string & str)198 napi_value Convert2JSValue(napi_env env, const std::string &str)
199 {
200 napi_value value = nullptr;
201 if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
202 return nullptr;
203 }
204 return value;
205 }
206
Convert2JSValue(napi_env env,const std::vector<TaskState> & taskStates)207 napi_value Convert2JSValue(napi_env env, const std::vector<TaskState> &taskStates)
208 {
209 napi_value value = nullptr;
210 napi_create_array_with_length(env, taskStates.size(), &value);
211 int index = 0;
212 for (const auto &taskState : taskStates) {
213 napi_value jsTaskState = nullptr;
214 napi_create_object(env, &jsTaskState);
215 napi_set_named_property(env, jsTaskState, "path", Convert2JSValue(env, taskState.path));
216 napi_set_named_property(env, jsTaskState, "responseCode", Convert2JSValue(env, taskState.responseCode));
217 napi_set_named_property(env, jsTaskState, "message", Convert2JSValue(env, taskState.message));
218 napi_set_element(env, value, index++, jsTaskState);
219 }
220 return value;
221 }
222
Convert2JSValue(napi_env env,const Progress & progress)223 napi_value Convert2JSValue(napi_env env, const Progress &progress)
224 {
225 napi_value value = nullptr;
226 napi_create_object(env, &value);
227 napi_set_named_property(env, value, "state", Convert2JSValue(env, static_cast<uint32_t>(progress.state)));
228 napi_set_named_property(env, value, "index", Convert2JSValue(env, progress.index));
229 napi_set_named_property(env, value, "processed", Convert2JSValue(env, progress.processed));
230 napi_set_named_property(env, value, "sizes", Convert2JSValue(env, progress.sizes));
231 napi_set_named_property(
232 env, value, "extras", Convert2JSHeadersAndBody(env, progress.extras, progress.bodyBytes, false));
233 return value;
234 }
235
Convert2JSValue(napi_env env,const std::vector<FileSpec> & files,const std::vector<FormItem> & forms)236 napi_value Convert2JSValue(napi_env env, const std::vector<FileSpec> &files, const std::vector<FormItem> &forms)
237 {
238 napi_value data = nullptr;
239 size_t filesLen = files.size();
240 size_t formsLen = forms.size();
241 napi_create_array_with_length(env, filesLen + formsLen, &data);
242 size_t i = 0;
243 for (; i < formsLen; i++) {
244 napi_value object = nullptr;
245 napi_create_object(env, &object);
246 napi_set_named_property(env, object, "name", Convert2JSValue(env, forms[i].name));
247 napi_set_named_property(env, object, "value", Convert2JSValue(env, forms[i].value));
248 napi_set_element(env, data, i, object);
249 }
250 for (size_t j = 0; j < filesLen; j++) {
251 napi_value fileSpec = nullptr;
252 napi_create_object(env, &fileSpec);
253 napi_set_named_property(env, fileSpec, "path", Convert2JSValue(env, files[j].uri));
254 napi_set_named_property(env, fileSpec, "mimeType", Convert2JSValue(env, files[j].type));
255 napi_set_named_property(env, fileSpec, "filename", Convert2JSValue(env, files[j].filename));
256 napi_value object = nullptr;
257 napi_create_object(env, &object);
258 napi_set_named_property(env, object, "name", Convert2JSValue(env, files[j].name));
259 napi_set_named_property(env, object, "value", fileSpec);
260 napi_set_element(env, data, i, object);
261 i++;
262 }
263 return data;
264 }
265
Convert2JSValue(napi_env env,TaskInfo & taskInfo)266 napi_value Convert2JSValue(napi_env env, TaskInfo &taskInfo)
267 {
268 napi_value value = nullptr;
269 napi_create_object(env, &value);
270 if (taskInfo.withSystem) {
271 napi_set_named_property(env, value, "uid", Convert2JSValue(env, taskInfo.uid));
272 napi_set_named_property(env, value, "bundle", Convert2JSValue(env, taskInfo.bundle));
273 taskInfo.url = "";
274 taskInfo.data = "";
275 if (taskInfo.action == Action::UPLOAD) {
276 taskInfo.files.clear();
277 taskInfo.forms.clear();
278 }
279 }
280 napi_set_named_property(env, value, "url", Convert2JSValue(env, taskInfo.url));
281 napi_set_named_property(env, value, "saveas", Convert2JSValue(env, GetSaveas(taskInfo.files, taskInfo.action)));
282 if (taskInfo.action == Action::DOWNLOAD) {
283 napi_set_named_property(env, value, "data", Convert2JSValue(env, taskInfo.data));
284 } else {
285 napi_set_named_property(env, value, "data", Convert2JSValue(env, taskInfo.files, taskInfo.forms));
286 }
287 napi_set_named_property(env, value, "tid", Convert2JSValue(env, taskInfo.tid));
288 napi_set_named_property(env, value, "title", Convert2JSValue(env, taskInfo.title));
289 napi_set_named_property(env, value, "description", Convert2JSValue(env, taskInfo.description));
290 napi_set_named_property(env, value, "action", Convert2JSValue(env, static_cast<uint32_t>(taskInfo.action)));
291 napi_set_named_property(env, value, "mode", Convert2JSValue(env, static_cast<uint32_t>(taskInfo.mode)));
292 napi_set_named_property(env, value, "mimeType", Convert2JSValue(env, taskInfo.mimeType));
293 napi_set_named_property(env, value, "progress", Convert2JSValue(env, taskInfo.progress));
294 napi_set_named_property(env, value, "gauge", Convert2JSValue(env, taskInfo.gauge));
295 napi_set_named_property(env, value, "priority", Convert2JSValue(env, taskInfo.priority));
296 napi_set_named_property(env, value, "ctime", Convert2JSValue(env, taskInfo.ctime));
297 napi_set_named_property(env, value, "mtime", Convert2JSValue(env, taskInfo.mtime));
298 napi_set_named_property(env, value, "retry", Convert2JSValue(env, taskInfo.retry));
299 napi_set_named_property(env, value, "tries", Convert2JSValue(env, taskInfo.tries));
300 if (taskInfo.code == Reason::REASON_OK) {
301 napi_value value1 = nullptr;
302 napi_get_null(env, &value1);
303 napi_set_named_property(env, value, "faults", value1);
304 } else {
305 Faults fault = CommonUtils::GetFaultByReason(taskInfo.code);
306 napi_set_named_property(env, value, "faults", Convert2JSValue(env, static_cast<uint32_t>(fault)));
307 }
308 napi_set_named_property(env, value, "reason", Convert2JSValue(env, CommonUtils::GetMsgByReason(taskInfo.code)));
309 napi_set_named_property(env, value, "extras", Convert2JSValue(env, taskInfo.extras));
310 return value;
311 }
312
Convert2JSValueConfig(napi_env env,Config & config)313 napi_value Convert2JSValueConfig(napi_env env, Config &config)
314 {
315 napi_value value = nullptr;
316 napi_create_object(env, &value);
317 napi_set_named_property(env, value, "action", Convert2JSValue(env, static_cast<uint32_t>(config.action)));
318 napi_set_named_property(env, value, "url", Convert2JSValue(env, config.url));
319 napi_set_named_property(env, value, "title", Convert2JSValue(env, config.title));
320 napi_set_named_property(env, value, "description", Convert2JSValue(env, config.description));
321 napi_set_named_property(env, value, "mode", Convert2JSValue(env, static_cast<uint32_t>(config.mode)));
322 napi_set_named_property(env, value, "overwrite", Convert2JSValue(env, config.overwrite));
323 napi_set_named_property(env, value, "method", Convert2JSValue(env, config.method));
324 napi_set_named_property(env, value, "headers", Convert2JSValue(env, config.headers));
325 if (config.action == Action::DOWNLOAD) {
326 napi_set_named_property(env, value, "data", Convert2JSValue(env, config.data));
327 } else {
328 napi_set_named_property(env, value, "data", Convert2JSValue(env, config.files, config.forms));
329 }
330 napi_set_named_property(env, value, "saveas", Convert2JSValue(env, config.saveas));
331 napi_set_named_property(env, value, "network", Convert2JSValue(env, static_cast<uint32_t>(config.network)));
332 napi_set_named_property(env, value, "metered", Convert2JSValue(env, config.metered));
333 napi_set_named_property(env, value, "roaming", Convert2JSValue(env, config.roaming));
334 napi_set_named_property(env, value, "retry", Convert2JSValue(env, config.retry));
335 napi_set_named_property(env, value, "redirect", Convert2JSValue(env, config.redirect));
336 napi_set_named_property(env, value, "index", Convert2JSValue(env, config.index));
337 napi_set_named_property(env, value, "begins", Convert2JSValue(env, config.begins));
338 napi_set_named_property(env, value, "ends", Convert2JSValue(env, config.ends));
339 napi_set_named_property(env, value, "priority", Convert2JSValue(env, config.priority));
340 napi_set_named_property(env, value, "gauge", Convert2JSValue(env, config.gauge));
341 napi_set_named_property(env, value, "precise", Convert2JSValue(env, config.precise));
342 if (config.token != "null") {
343 napi_set_named_property(env, value, "token", Convert2JSValue(env, config.token));
344 }
345 napi_set_named_property(env, value, "extras", Convert2JSValue(env, config.extras));
346 napi_set_named_property(env, value, "multipart", Convert2JSValue(env, config.multipart));
347 return value;
348 }
349
Convert2JSValue(napi_env env,const std::shared_ptr<Response> & response)350 napi_value Convert2JSValue(napi_env env, const std::shared_ptr<Response> &response)
351 {
352 napi_value value = nullptr;
353 napi_create_object(env, &value);
354 napi_set_named_property(env, value, "version", Convert2JSValue(env, response->version));
355 napi_set_named_property(env, value, "statusCode", Convert2JSValue(env, response->statusCode));
356 napi_set_named_property(env, value, "reason", Convert2JSValue(env, response->reason));
357 napi_set_named_property(env, value, "headers", Convert2JSHeaders(env, response->headers));
358 return value;
359 }
360
Convert2JSHeaders(napi_env env,const std::map<std::string,std::vector<std::string>> & headers)361 napi_value Convert2JSHeaders(napi_env env, const std::map<std::string, std::vector<std::string>> &headers)
362 {
363 napi_value value = nullptr;
364 napi_value value2 = nullptr;
365 napi_value global = nullptr;
366 napi_value mapConstructor = nullptr;
367 napi_value mapSet = nullptr;
368 const uint32_t paramNumber = 2;
369 napi_value args[paramNumber] = { 0 };
370
371 napi_status status = napi_get_global(env, &global);
372 if (status != napi_ok) {
373 REQUEST_HILOGE("response napi_get_global failed");
374 return nullptr;
375 }
376
377 status = napi_get_named_property(env, global, "Map", &mapConstructor);
378 if (status != napi_ok) {
379 REQUEST_HILOGE("response map failed");
380 return nullptr;
381 }
382
383 status = napi_new_instance(env, mapConstructor, 0, nullptr, &value);
384 if (status != napi_ok) {
385 REQUEST_HILOGE("response napi_new_instance failed");
386 return nullptr;
387 }
388
389 status = napi_get_named_property(env, value, "set", &mapSet);
390 if (status != napi_ok) {
391 REQUEST_HILOGE("response set failed");
392 return nullptr;
393 }
394
395 for (const auto &it : headers) {
396 args[0] = Convert2JSValue(env, it.first);
397 args[1] = Convert2JSValue(env, it.second);
398 status = napi_call_function(env, value, mapSet, paramNumber, args, &value2);
399 if (status != napi_ok) {
400 REQUEST_HILOGE("response napi_call_function failed, %{public}d", status);
401 return nullptr;
402 }
403 }
404 return value;
405 }
406
GetSaveas(const std::vector<FileSpec> & files,Action action)407 std::string GetSaveas(const std::vector<FileSpec> &files, Action action)
408 {
409 if (action == Action::UPLOAD) {
410 return "";
411 }
412 if (files.empty()) {
413 return "";
414 }
415 return files[0].uri;
416 }
417
Convert2Boolean(napi_env env,napi_value object,const std::string & propertyName)418 bool Convert2Boolean(napi_env env, napi_value object, const std::string &propertyName)
419 {
420 if (!HasNamedProperty(env, object, propertyName)) {
421 return false;
422 }
423 napi_value value = GetNamedProperty(env, object, propertyName);
424 if (GetValueType(env, value) != napi_boolean) {
425 return false;
426 }
427 bool ret = false;
428 NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
429 return ret;
430 }
431
Convert2Uint32(napi_env env,napi_value value)432 uint32_t Convert2Uint32(napi_env env, napi_value value)
433 {
434 uint32_t ret = 0;
435 NAPI_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
436 return ret;
437 }
438
Convert2Uint32(napi_env env,napi_value object,const std::string & propertyName)439 uint32_t Convert2Uint32(napi_env env, napi_value object, const std::string &propertyName)
440 {
441 if (!HasNamedProperty(env, object, propertyName)) {
442 return 0;
443 }
444 napi_value value = GetNamedProperty(env, object, propertyName);
445 if (GetValueType(env, value) != napi_number) {
446 return 0;
447 }
448 return Convert2Uint32(env, value);
449 }
450
Convert2Int32(napi_env env,napi_value value)451 int32_t Convert2Int32(napi_env env, napi_value value)
452 {
453 int32_t ret = 0;
454 NAPI_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
455 return ret;
456 }
457
Convert2Int64(napi_env env,napi_value value)458 int64_t Convert2Int64(napi_env env, napi_value value)
459 {
460 int64_t ret = 0;
461 NAPI_CALL_BASE(env, napi_get_value_int64(env, value, &ret), 0);
462 return ret;
463 }
464
Convert2Int64(napi_env env,napi_value object,const std::string & propertyName)465 int64_t Convert2Int64(napi_env env, napi_value object, const std::string &propertyName)
466 {
467 if (!HasNamedProperty(env, object, propertyName)) {
468 return 0;
469 }
470 napi_value value = GetNamedProperty(env, object, propertyName);
471 if (GetValueType(env, value) != napi_number) {
472 return 0;
473 }
474 return Convert2Int64(env, value);
475 }
476
Convert2String(napi_env env,napi_value value)477 std::string Convert2String(napi_env env, napi_value value)
478 {
479 std::string result;
480 std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
481 size_t length = 0;
482 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
483 if (length > 0) {
484 return result.append(&str[0], length);
485 }
486 return result;
487 }
488
Convert2String(napi_env env,napi_value object,const std::string & propertyName)489 std::string Convert2String(napi_env env, napi_value object, const std::string &propertyName)
490 {
491 if (!HasNamedProperty(env, object, propertyName)) {
492 return "";
493 }
494 napi_value value = GetNamedProperty(env, object, propertyName);
495 if (GetValueType(env, value) != napi_string) {
496 return "";
497 }
498 return Convert2String(env, value);
499 }
500
ThrowError(napi_env env,ExceptionErrorCode code,const std::string & msg,bool withErrCode)501 void ThrowError(napi_env env, ExceptionErrorCode code, const std::string &msg, bool withErrCode)
502 {
503 napi_value error = CreateBusinessError(env, code, msg, withErrCode);
504 napi_throw(env, error);
505 }
506
ConvertError(int32_t errorCode,ExceptionError & err)507 void ConvertError(int32_t errorCode, ExceptionError &err)
508 {
509 auto generateError = [&err](ExceptionErrorCode errorCode, const std::string &info) {
510 err.code = errorCode;
511 err.errInfo = info;
512 REQUEST_HILOGE("errorCode: %{public}d, errInfo: %{public}s", err.code, err.errInfo.c_str());
513 };
514
515 switch (errorCode) {
516 case E_UNLOADING_SA:
517 generateError(E_SERVICE_ERROR, "Service ability is quitting.");
518 break;
519 case E_IPC_SIZE_TOO_LARGE:
520 generateError(E_SERVICE_ERROR, "Ipc error.");
521 break;
522 case E_MIMETYPE_NOT_FOUND:
523 generateError(E_OTHER, "Mimetype not found.");
524 break;
525 case E_TASK_INDEX_TOO_LARGE:
526 generateError(E_TASK_NOT_FOUND, "Task index out of range.");
527 break;
528 default:
529 generateError(static_cast<ExceptionErrorCode>(errorCode), "");
530 break;
531 }
532 }
533
CreateBusinessError(napi_env env,ExceptionErrorCode errorCode,const std::string & errorMessage,bool withErrCode)534 napi_value CreateBusinessError(
535 napi_env env, ExceptionErrorCode errorCode, const std::string &errorMessage, bool withErrCode)
536 {
537 napi_value error = nullptr;
538 napi_value msg = nullptr;
539 auto iter = ErrorCodeToMsg.find(errorCode);
540 std::string strMsg = (iter != ErrorCodeToMsg.end() ? iter->second : "") + " " + errorMessage;
541 NAPI_CALL(env, napi_create_string_utf8(env, strMsg.c_str(), strMsg.length(), &msg));
542 NAPI_CALL(env, napi_create_error(env, nullptr, msg, &error));
543 if (!withErrCode) {
544 return error;
545 }
546 napi_value code = nullptr;
547 NAPI_CALL(env, napi_create_uint32(env, static_cast<uint32_t>(errorCode), &code));
548 napi_set_named_property(env, error, "code", code);
549 return error;
550 }
551
GetValueType(napi_env env,napi_value value)552 napi_valuetype GetValueType(napi_env env, napi_value value)
553 {
554 if (value == nullptr) {
555 return napi_undefined;
556 }
557
558 napi_valuetype valueType = napi_undefined;
559 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
560 return valueType;
561 }
562
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)563 bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
564 {
565 bool hasProperty = false;
566 NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
567 return hasProperty;
568 }
569
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)570 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
571 {
572 napi_value value = nullptr;
573 bool hasProperty = false;
574 NAPI_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
575 if (!hasProperty) {
576 return value;
577 }
578 NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
579 return value;
580 }
581
GetPropertyNames(napi_env env,napi_value object)582 std::vector<std::string> GetPropertyNames(napi_env env, napi_value object)
583 {
584 std::vector<std::string> ret;
585 napi_value names = nullptr;
586 NAPI_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
587 uint32_t length = 0;
588 NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
589 for (uint32_t index = 0; index < length; ++index) {
590 napi_value name = nullptr;
591 if (napi_get_element(env, names, index, &name) != napi_ok) {
592 continue;
593 }
594 if (GetValueType(env, name) != napi_string) {
595 continue;
596 }
597 ret.emplace_back(Convert2String(env, name));
598 }
599 return ret;
600 }
601
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)602 void SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
603 {
604 napi_value jsValue = Convert2JSValue(env, value);
605 if (GetValueType(env, jsValue) != napi_number) {
606 return;
607 }
608
609 napi_set_named_property(env, object, name.c_str(), jsValue);
610 }
611
SetInt64Property(napi_env env,napi_value object,const std::string & name,int64_t value)612 void SetInt64Property(napi_env env, napi_value object, const std::string &name, int64_t value)
613 {
614 napi_value jsValue = Convert2JSValue(env, value);
615 if (GetValueType(env, jsValue) != napi_number) {
616 return;
617 }
618
619 napi_set_named_property(env, object, name.c_str(), jsValue);
620 }
621
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)622 void SetStringPropertyUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value)
623 {
624 napi_value jsValue = Convert2JSValue(env, value);
625 if (GetValueType(env, jsValue) != napi_string) {
626 return;
627 }
628 napi_set_named_property(env, object, name.c_str(), jsValue);
629 }
630
CreateObject(napi_env env)631 napi_value CreateObject(napi_env env)
632 {
633 napi_value object = nullptr;
634 NAPI_CALL(env, napi_create_object(env, &object));
635 return object;
636 }
637
GetUndefined(napi_env env)638 napi_value GetUndefined(napi_env env)
639 {
640 napi_value undefined = nullptr;
641 NAPI_CALL(env, napi_get_undefined(env, &undefined));
642 return undefined;
643 }
644
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)645 napi_value CallFunction(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
646 {
647 napi_value res = nullptr;
648 NAPI_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
649 return res;
650 }
651
ToLower(const std::string & s)652 std::string ToLower(const std::string &s)
653 {
654 std::string res = s;
655 std::transform(res.begin(), res.end(), res.begin(), tolower);
656 return res;
657 }
658
GetRequestAction(napi_env env,napi_value configValue)659 Action GetRequestAction(napi_env env, napi_value configValue)
660 {
661 if (HasNamedProperty(env, configValue, PARAM_KEY_METHOD) || HasNamedProperty(env, configValue, PARAM_KEY_FILES)
662 || HasNamedProperty(env, configValue, PARAM_KEY_DATA)) {
663 return Action::UPLOAD;
664 }
665 return Action::DOWNLOAD;
666 }
667
Convert2FileVector(napi_env env,napi_value jsFiles,const std::string & version)668 std::vector<FileSpec> Convert2FileVector(napi_env env, napi_value jsFiles, const std::string &version)
669 {
670 bool isArray = false;
671 napi_is_array(env, jsFiles, &isArray);
672 NAPI_ASSERT_BASE(env, isArray, "not array", {});
673 uint32_t length = 0;
674 napi_get_array_length(env, jsFiles, &length);
675 std::vector<FileSpec> files;
676 for (uint32_t i = 0; i < length; ++i) {
677 napi_value jsFile = nullptr;
678 napi_handle_scope scope = nullptr;
679 napi_open_handle_scope(env, &scope);
680 if (scope == nullptr) {
681 continue;
682 }
683 napi_get_element(env, jsFiles, i, &jsFile);
684 if (jsFile == nullptr) {
685 napi_close_handle_scope(env, scope);
686 continue;
687 }
688 FileSpec file;
689 bool ret = Convert2File(env, jsFile, file);
690 if (!ret) {
691 napi_close_handle_scope(env, scope);
692 continue;
693 }
694 files.push_back(file);
695 napi_close_handle_scope(env, scope);
696 }
697 return files;
698 }
699
Convert2File(napi_env env,napi_value jsFile,FileSpec & file)700 bool Convert2File(napi_env env, napi_value jsFile, FileSpec &file)
701 {
702 napi_value filename = GetNamedProperty(env, jsFile, "filename");
703 if (filename == nullptr) {
704 return false;
705 }
706 file.filename = Convert2String(env, filename);
707
708 napi_value name = GetNamedProperty(env, jsFile, "name");
709 if (name == nullptr) {
710 return false;
711 }
712 file.name = Convert2String(env, name);
713
714 napi_value uri = GetNamedProperty(env, jsFile, "uri");
715 if (uri == nullptr) {
716 return false;
717 }
718 file.uri = Convert2String(env, uri);
719
720 napi_value type = GetNamedProperty(env, jsFile, "type");
721 if (type == nullptr) {
722 return false;
723 }
724 std::string mimeType = Convert2String(env, type);
725 // If it is empty, it need to be reset.
726 if (!mimeType.empty()) {
727 file.hasContentType = true;
728 file.type = mimeType;
729 }
730 return true;
731 }
732
Convert2RequestDataVector(napi_env env,napi_value jsRequestDatas)733 std::vector<FormItem> Convert2RequestDataVector(napi_env env, napi_value jsRequestDatas)
734 {
735 bool isArray = false;
736 napi_is_array(env, jsRequestDatas, &isArray);
737 NAPI_ASSERT_BASE(env, isArray, "not array", {});
738 uint32_t length = 0;
739 napi_get_array_length(env, jsRequestDatas, &length);
740 std::vector<FormItem> requestDatas;
741 for (uint32_t i = 0; i < length; ++i) {
742 napi_value requestData = nullptr;
743 napi_get_element(env, jsRequestDatas, i, &requestData);
744 if (requestData == nullptr) {
745 continue;
746 }
747 requestDatas.push_back(Convert2RequestData(env, requestData));
748 }
749 return requestDatas;
750 }
751
Convert2RequestData(napi_env env,napi_value jsRequestData)752 FormItem Convert2RequestData(napi_env env, napi_value jsRequestData)
753 {
754 FormItem requestData;
755 napi_value value = nullptr;
756 napi_get_named_property(env, jsRequestData, "name", &value);
757 if (value != nullptr) {
758 requestData.name = Convert2String(env, value);
759 }
760 value = nullptr;
761 napi_get_named_property(env, jsRequestData, "value", &value);
762 if (value != nullptr) {
763 requestData.value = Convert2String(env, value);
764 }
765 return requestData;
766 }
767
IsPathValid(const std::string & filePath)768 bool IsPathValid(const std::string &filePath)
769 {
770 auto path = filePath.substr(0, filePath.rfind('/'));
771 char resolvedPath[PATH_MAX + 1] = { 0 };
772 if (path.length() > PATH_MAX || realpath(path.c_str(), resolvedPath) == nullptr
773 || strncmp(resolvedPath, path.c_str(), path.length()) != 0) {
774 REQUEST_HILOGE("invalid file path!");
775 return false;
776 }
777 return true;
778 }
779
SHA256(const char * str,size_t len)780 std::string SHA256(const char *str, size_t len)
781 {
782 unsigned char hash[SHA256_DIGEST_LENGTH];
783 SHA256_CTX sha256;
784 SHA256_Init(&sha256);
785 SHA256_Update(&sha256, str, len);
786 SHA256_Final(hash, &sha256);
787 std::stringstream ss;
788 for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
789 // 2 means setting the width of the output.
790 ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
791 }
792 return ss.str();
793 }
794
ReadBytesFromFile(const std::string & filePath,std::vector<uint8_t> & fileData)795 void ReadBytesFromFile(const std::string &filePath, std::vector<uint8_t> &fileData)
796 {
797 // Ensure filePath validity.
798 std::ifstream inputFile(filePath.c_str(), std::ios::binary);
799 if (inputFile.is_open()) {
800 inputFile.seekg(0, std::ios::end);
801 fileData.resize(inputFile.tellg());
802 inputFile.seekg(0);
803 inputFile.read(reinterpret_cast<char *>(fileData.data()), fileData.size());
804 inputFile.close();
805 } else {
806 REQUEST_HILOGW("Read bytes from file, invalid file path!");
807 }
808 return;
809 }
810
RemoveFile(const std::string & filePath)811 void RemoveFile(const std::string &filePath)
812 {
813 auto removeFile = [filePath]() -> void {
814 std::remove(filePath.c_str());
815 return;
816 };
817 ffrt::submit(removeFile, {}, {}, ffrt::task_attr().name("Os_Request_Rm").qos(ffrt::qos_default));
818 }
819 } // namespace OHOS::Request::NapiUtils