1 /*
2 * Copyright (c) 2022 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 "js_util.h"
17 #include <securec.h>
18
19 using namespace OHOS::Request::Upload;
20 namespace OHOS::Request::UploadNapi {
Convert2String(napi_env env,napi_value jsString)21 std::string JSUtil::Convert2String(napi_env env, napi_value jsString)
22 {
23 size_t maxLen = JSUtil::MAX_LEN;
24 napi_status status = napi_get_value_string_utf8(env, jsString, NULL, 0, &maxLen);
25 if (status != napi_ok) {
26 GET_AND_THROW_LAST_ERROR((env));
27 maxLen = JSUtil::MAX_LEN;
28 }
29 if (maxLen == 0) {
30 return std::string();
31 }
32 char *buf = new char[maxLen + 1];
33 if (buf == nullptr) {
34 return std::string();
35 }
36 size_t len = 0;
37 status = napi_get_value_string_utf8(env, jsString, buf, maxLen + 1, &len);
38 if (status != napi_ok) {
39 GET_AND_THROW_LAST_ERROR((env));
40 }
41 buf[len] = 0;
42 std::string value(buf);
43 delete[] buf;
44 return value;
45 }
46
Convert2StrVector(napi_env env,napi_value value)47 std::vector<std::string> JSUtil::Convert2StrVector(napi_env env, napi_value value)
48 {
49 uint32_t arrLen = 0;
50 napi_get_array_length(env, value, &arrLen);
51 if (arrLen == 0) {
52 return {};
53 }
54 std::vector<std::string> result;
55 for (size_t i = 0; i < arrLen; ++i) {
56 napi_value element;
57 napi_get_element(env, value, i, &element);
58 result.push_back(Convert2String(env, element));
59 }
60 return result;
61 }
62
Convert2Header(napi_env env,napi_value value)63 std::vector<std::string> JSUtil::Convert2Header(napi_env env, napi_value value)
64 {
65 std::vector<std::string> result;
66 napi_value keyArr = nullptr;
67 napi_status status = napi_get_property_names(env, value, &keyArr);
68 if (status != napi_ok) {
69 return result;
70 }
71
72 uint32_t len = 0;
73 status = napi_get_array_length(env, keyArr, &len);
74 if (status != napi_ok) {
75 UPLOAD_HILOGE(UPLOAD_MODULE_JS_NAPI, "Convert2Header. napi_get_array_length statue Error");
76 return result;
77 }
78 for (uint32_t i = 0; i < len; i++) {
79 napi_value keyNapiValue = nullptr;
80 napi_get_element(env, keyArr, i, &keyNapiValue);
81
82 napi_valuetype valueType;
83 napi_typeof(env, keyNapiValue, &valueType);
84 if (valueType != napi_valuetype::napi_string) {
85 continue;
86 }
87
88 char key[JSUtil::MAX_LEN] = { 0 };
89 size_t cValueLength = 0;
90 napi_get_value_string_utf8(env, keyNapiValue, key, JSUtil::MAX_LEN - 1, &cValueLength);
91
92 napi_value jsvalue = nullptr;
93 napi_get_named_property(env, value, key, &jsvalue);
94 if (jsvalue != nullptr) {
95 std::string item(key);
96 item.append(": ");
97 item.append(Convert2String(env, jsvalue));
98 UPLOAD_HILOGD(UPLOAD_MODULE_JS_NAPI, "Convert2Header is %{public}s", item.c_str());
99 result.push_back(item);
100 }
101 }
102 return result;
103 }
104
Convert2JSStringVector(napi_env env,const std::vector<std::string> & cStrings)105 napi_value JSUtil::Convert2JSStringVector(napi_env env, const std::vector<std::string> &cStrings)
106 {
107 napi_value jsStrings = nullptr;
108 napi_create_array_with_length(env, cStrings.size(), &jsStrings);
109 int index = 0;
110 for (const auto &cString : cStrings) {
111 napi_value jsString = Convert2JSString(env, cString);
112 napi_set_element(env, jsStrings, index++, jsString);
113 }
114 return jsStrings;
115 }
116
Convert2JSUploadResponse(napi_env env,const Upload::UploadResponse & response)117 napi_value JSUtil::Convert2JSUploadResponse(napi_env env, const Upload::UploadResponse &response)
118 {
119 napi_value jsResponse = nullptr;
120 napi_create_object(env, &jsResponse);
121 napi_set_named_property(env, jsResponse, "code", Convert2JSValue(env, response.code));
122 napi_set_named_property(env, jsResponse, "data", Convert2JSString(env, response.data));
123 napi_set_named_property(env, jsResponse, "headers", Convert2JSString(env, response.headers));
124 return jsResponse;
125 }
126
Convert2JSValue(napi_env env,int32_t value)127 napi_value JSUtil::Convert2JSValue(napi_env env, int32_t value)
128 {
129 napi_value jsValue;
130 napi_status status = napi_create_int32(env, value, &jsValue);
131 if (status != napi_ok) {
132 return nullptr;
133 }
134 return jsValue;
135 }
136
ParseFunction(napi_env env,napi_value & object,const char * name,bool & hasFunction,napi_ref & output)137 void JSUtil::ParseFunction(napi_env env, napi_value &object, const char *name, bool &hasFunction, napi_ref &output)
138 {
139 napi_value value = nullptr;
140 if (napi_get_named_property(env, object, name, &value) == napi_ok) {
141 napi_valuetype valueType = napi_null;
142 NAPI_CALL_RETURN_VOID(env, napi_typeof(env, value, &valueType));
143 NAPI_ASSERT_RETURN_VOID(env, valueType == napi_function, "Wrong argument, function expected.");
144 NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, value, 1, &output));
145 hasFunction = true;
146 }
147 }
148
Convert2JSString(napi_env env,const std::string & cString)149 napi_value JSUtil::Convert2JSString(napi_env env, const std::string &cString)
150 {
151 napi_value jsValue = nullptr;
152 napi_create_string_utf8(env, cString.c_str(), cString.size(), &jsValue);
153 return jsValue;
154 }
155
Convert2UploadConfig(napi_env env,napi_value jsConfig)156 std::shared_ptr<Upload::UploadConfig> JSUtil::Convert2UploadConfig(napi_env env, napi_value jsConfig)
157 {
158 Upload::UploadConfig config;
159 napi_value value = nullptr;
160 napi_get_named_property(env, jsConfig, "url", &value);
161 if (value != nullptr) {
162 config.url = Convert2String(env, value);
163 }
164 value = nullptr;
165 napi_get_named_property(env, jsConfig, "header", &value);
166 if (value != nullptr) {
167 config.header = Convert2Header(env, value);
168 }
169 value = nullptr;
170 napi_get_named_property(env, jsConfig, "method", &value);
171 if (value != nullptr) {
172 config.method = Convert2String(env, value);
173 }
174 value = nullptr;
175 napi_get_named_property(env, jsConfig, "files", &value);
176 if (value != nullptr) {
177 config.files = Convert2FileVector(env, value);
178 }
179 value = nullptr;
180 napi_get_named_property(env, jsConfig, "data", &value);
181 if (value != nullptr) {
182 config.data = Convert2RequestDataVector(env, value);
183 }
184
185 std::shared_ptr<Upload::UploadConfig> tmpConfig = std::make_shared<Upload::UploadConfig>(config);
186 return tmpConfig;
187 }
188
Convert2JSUploadConfig(napi_env env,const Upload::UploadConfig & config)189 napi_value JSUtil::Convert2JSUploadConfig(napi_env env, const Upload::UploadConfig &config)
190 {
191 napi_value jsConfig = nullptr;
192 napi_create_object(env, &jsConfig);
193 napi_set_named_property(env, jsConfig, "url", Convert2JSString(env, config.url));
194 napi_set_named_property(env, jsConfig, "header", Convert2JSStringVector(env, config.header));
195 napi_set_named_property(env, jsConfig, "method", Convert2JSString(env, config.method));
196 napi_set_named_property(env, jsConfig, "files", Convert2JSFileVector(env, config.files));
197 napi_set_named_property(env, jsConfig, "data", Convert2JSRequestDataVector(env, config.data));
198 return jsConfig;
199 }
200
Convert2File(napi_env env,napi_value jsFile)201 Upload::File JSUtil::Convert2File(napi_env env, napi_value jsFile)
202 {
203 Upload::File file;
204 napi_value value = nullptr;
205 napi_get_named_property(env, jsFile, "filename", &value);
206 if (value != nullptr) {
207 file.filename = Convert2String(env, value);
208 }
209 value = nullptr;
210 napi_get_named_property(env, jsFile, "name", &value);
211 if (value != nullptr) {
212 file.name = Convert2String(env, value);
213 }
214 value = nullptr;
215 napi_get_named_property(env, jsFile, "uri", &value);
216 if (value != nullptr) {
217 file.uri = Convert2String(env, value);
218 }
219 value = nullptr;
220 napi_get_named_property(env, jsFile, "type", &value);
221 if (value != nullptr) {
222 file.type = Convert2String(env, value);
223 }
224 return file;
225 }
226
Convert2JSFile(napi_env env,const Upload::File & file)227 napi_value JSUtil::Convert2JSFile(napi_env env, const Upload::File &file)
228 {
229 napi_value jsFile = nullptr;
230 napi_create_object(env, &jsFile);
231 napi_set_named_property(env, jsFile, "filename", Convert2JSString(env, file.filename));
232 napi_set_named_property(env, jsFile, "name", Convert2JSString(env, file.name));
233 napi_set_named_property(env, jsFile, "uri", Convert2JSString(env, file.uri));
234 napi_set_named_property(env, jsFile, "type", Convert2JSString(env, file.type));
235 return jsFile;
236 }
237
Convert2FileVector(napi_env env,napi_value jsFiles)238 std::vector<Upload::File> JSUtil::Convert2FileVector(napi_env env, napi_value jsFiles)
239 {
240 bool isArray = false;
241 napi_is_array(env, jsFiles, &isArray);
242 NAPI_ASSERT_BASE(env, isArray, "not array", { });
243 uint32_t length = 0;
244 napi_get_array_length(env, jsFiles, &length);
245 std::vector<Upload::File> files;
246 for (uint32_t i = 0; i < length; ++i) {
247 napi_value file = nullptr;
248 napi_get_element(env, jsFiles, i, &file);
249 if (file == nullptr) {
250 continue;
251 }
252 files.push_back(Convert2File(env, file));
253 }
254 return files;
255 }
256
Convert2JSFileVector(napi_env env,const std::vector<Upload::File> & files)257 napi_value JSUtil::Convert2JSFileVector(napi_env env, const std::vector<Upload::File> &files)
258 {
259 napi_value jsFiles = nullptr;
260 napi_create_array_with_length(env, files.size(), &jsFiles);
261 int index = 0;
262 for (const auto &file : files) {
263 napi_value jsFile = Convert2JSFile(env, file);
264 napi_set_element(env, jsFiles, index++, jsFile);
265 }
266 return jsFiles;
267 }
268
Convert2RequestData(napi_env env,napi_value jsRequestData)269 Upload::RequestData JSUtil::Convert2RequestData(napi_env env, napi_value jsRequestData)
270 {
271 Upload::RequestData requestData;
272 napi_value value = nullptr;
273 napi_get_named_property(env, jsRequestData, "name", &value);
274 if (value != nullptr) {
275 requestData.name = Convert2String(env, value);
276 }
277 value = nullptr;
278 napi_get_named_property(env, jsRequestData, "value", &value);
279 if (value != nullptr) {
280 requestData.value = Convert2String(env, value);
281 }
282 return requestData;
283 }
284
Convert2JSRequestData(napi_env env,const Upload::RequestData & requestData)285 napi_value JSUtil::Convert2JSRequestData(napi_env env, const Upload::RequestData &requestData)
286 {
287 napi_value jsRequestData = nullptr;
288 napi_create_object(env, &jsRequestData);
289 napi_set_named_property(env, jsRequestData, "name", Convert2JSString(env, requestData.name));
290 napi_set_named_property(env, jsRequestData, "value", Convert2JSString(env, requestData.value));
291 return jsRequestData;
292 }
293
Convert2RequestDataVector(napi_env env,napi_value jsRequestDatas)294 std::vector<Upload::RequestData> JSUtil::Convert2RequestDataVector(napi_env env, napi_value jsRequestDatas)
295 {
296 bool isArray = false;
297 napi_is_array(env, jsRequestDatas, &isArray);
298 NAPI_ASSERT_BASE(env, isArray, "not array", { });
299 uint32_t length = 0;
300 napi_get_array_length(env, jsRequestDatas, &length);
301 std::vector<Upload::RequestData> requestDatas;
302 for (uint32_t i = 0; i < length; ++i) {
303 napi_value requestData = nullptr;
304 napi_get_element(env, jsRequestDatas, i, &requestData);
305 if (requestData == nullptr) {
306 continue;
307 }
308 requestDatas.push_back(Convert2RequestData(env, requestData));
309 }
310 return requestDatas;
311 }
312
Convert2JSRequestDataVector(napi_env env,const std::vector<Upload::RequestData> & requestDatas)313 napi_value JSUtil::Convert2JSRequestDataVector(napi_env env, const std::vector<Upload::RequestData> &requestDatas)
314 {
315 napi_value jsRequestDatas = nullptr;
316 napi_create_array_with_length(env, requestDatas.size(), &jsRequestDatas);
317 int index = 0;
318 for (const auto &requestData : requestDatas) {
319 napi_value jsRequestData = Convert2JSRequestData(env, requestData);
320 napi_set_element(env, jsRequestData, index++, jsRequestDatas);
321 }
322 return jsRequestDatas;
323 }
324 } // namespace OHOS::Request::UploadNapi