• 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 <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