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