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