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