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