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 #include "napi_zlib.h"
16
17 #include <cstring>
18 #include <uv.h>
19 #include <vector>
20
21 #include "app_log_wrapper.h"
22 #include "file_path.h"
23 #include "bundle_errors.h"
24 #include "business_error.h"
25 #include "common_func.h"
26 #include "napi/native_common.h"
27 #include "napi/native_node_api.h"
28 #include "napi_arg.h"
29 #include "napi_constants.h"
30 #include "napi_zlib_common.h"
31 #include "zip.h"
32 #include "zip_utils.h"
33 #include "zlib_callback_info.h"
34
35 using namespace OHOS::AppExecFwk;
36
37 namespace OHOS {
38 namespace AppExecFwk {
39 namespace LIBZIP {
40 namespace {
41 constexpr size_t ARGS_MAX_COUNT = 10;
42 constexpr int32_t PARAM3 = 3;
43 const char* WRONG_PARAM = "wrong param type";
44 }
45
46 #define COMPRESS_LEVE_CHECK(level, ret) \
47 if (!(level == COMPRESS_LEVEL_NO_COMPRESSION || level == COMPRESS_LEVEL_DEFAULT_COMPRESSION || \
48 level == COMPRESS_LEVEL_BEST_SPEED || level == COMPRESS_LEVEL_BEST_COMPRESSION)) { \
49 APP_LOGE("level parameter =[%{public}d] value is incorrect", (int)level); \
50 return ret; \
51 }
52
53 #define COMPRESS_STRATEGY_CHECK(strategy, false) \
54 if (!(strategy == COMPRESS_STRATEGY_DEFAULT_STRATEGY || strategy == COMPRESS_STRATEGY_FILTERED || \
55 strategy == COMPRESS_STRATEGY_HUFFMAN_ONLY || strategy == COMPRESS_STRATEGY_RLE || \
56 strategy == COMPRESS_STRATEGY_FIXED)) { \
57 APP_LOGE("strategy parameter= [%{public}d] value is incorrect", (int)strategy); \
58 return ret; \
59 }
60
61 #define COMPRESS_MEM_CHECK(mem, false) \
62 if (!(mem == MEM_LEVEL_MIN_MEMLEVEL || mem == MEM_LEVEL_DEFAULT_MEMLEVEL || mem == MEM_LEVEL_MAX_MEMLEVEL)) { \
63 APP_LOGE("memLevel parameter =[%{public}d] value is incorrect", (int)mem); \
64 return ret; \
65 }
66
67 void CompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo);
68 void DecompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo);
69 napi_value UnwrapZipParam(CallZipUnzipParam ¶m, napi_env env, napi_value *args, size_t argc);
70 napi_value UnwrapUnZipParam(CallZipUnzipParam ¶m, napi_env env, napi_value *args, size_t argc);
71 napi_value ZipFileWrap(napi_env env, napi_callback_info info, AsyncZipCallbackInfo *asyncZipCallbackInfo);
72 napi_value UnwrapStringParam(std::string &str, napi_env env, napi_value argv);
73 bool UnwrapOptionsParams(OPTIONS &options, napi_env env, napi_value arg);
74
75 /**
76 * @brief FlushType data initialization.
77 *
78 * @param env The environment that the Node-API call is invoked under.
79 * @param exports An empty object via the exports parameter as a convenience.
80 *
81 * @return The return value from Init is treated as the exports object for the module.
82 */
FlushTypeInit(napi_env env,napi_value exports)83 napi_value FlushTypeInit(napi_env env, napi_value exports)
84 {
85 APP_LOGD("%{public}s called.", __func__);
86 const int FLUSH_TYPE_NO_FLUSH = 0;
87 const int FLUSH_TYPE_PARTIAL_FLUSH = 1;
88 const int FLUSH_TYPE_SYNC_FLUSH = 2;
89 const int FLUSH_TYPE_FULL_FLUSH = 3;
90 const int FLUSH_TYPE_FINISH = 4;
91 const int FLUSH_TYPE_BLOCK = 5;
92 const int FLUSH_TYPE_TREES = 6;
93
94 napi_value flushType = nullptr;
95 napi_create_object(env, &flushType);
96 SetNamedProperty(env, flushType, "FLUSH_TYPE_NO_FLUSH", FLUSH_TYPE_NO_FLUSH);
97 SetNamedProperty(env, flushType, "FLUSH_TYPE_PARTIAL_FLUSH", FLUSH_TYPE_PARTIAL_FLUSH);
98 SetNamedProperty(env, flushType, "FLUSH_TYPE_SYNC_FLUSH", FLUSH_TYPE_SYNC_FLUSH);
99 SetNamedProperty(env, flushType, "FLUSH_TYPE_FULL_FLUSH", FLUSH_TYPE_FULL_FLUSH);
100 SetNamedProperty(env, flushType, "FLUSH_TYPE_FINISH", FLUSH_TYPE_FINISH);
101 SetNamedProperty(env, flushType, "FLUSH_TYPE_BLOCK", FLUSH_TYPE_BLOCK);
102 SetNamedProperty(env, flushType, "FLUSH_TYPE_TREES", FLUSH_TYPE_TREES);
103
104 napi_property_descriptor properties[] = {
105 DECLARE_NAPI_PROPERTY("FlushType", flushType),
106 };
107 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
108
109 return exports;
110 }
111 /**
112 * @brief CompressLevel data initialization.
113 *
114 * @param env The environment that the Node-API call is invoked under.
115 * @param exports An empty object via the exports parameter as a convenience.
116 *
117 * @return The return value from Init is treated as the exports object for the module.
118 */
CompressLevelInit(napi_env env,napi_value exports)119 napi_value CompressLevelInit(napi_env env, napi_value exports)
120 {
121 APP_LOGD("%{public}s called.", __func__);
122 const int COMPRESS_LEVEL_NO_COMPRESSION = 0;
123 const int COMPRESS_LEVEL_BEST_SPEED = 1;
124 const int COMPRESS_LEVEL_BEST_COMPRESSION = 9;
125 const int COMPRESS_LEVEL_DEFAULT_COMPRESSION = -1;
126
127 napi_value compressLevel = nullptr;
128 napi_create_object(env, &compressLevel);
129 SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_NO_COMPRESSION", COMPRESS_LEVEL_NO_COMPRESSION);
130 SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_BEST_SPEED", COMPRESS_LEVEL_BEST_SPEED);
131 SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_BEST_COMPRESSION", COMPRESS_LEVEL_BEST_COMPRESSION);
132 SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_DEFAULT_COMPRESSION", COMPRESS_LEVEL_DEFAULT_COMPRESSION);
133
134 napi_property_descriptor properties[] = {
135 DECLARE_NAPI_PROPERTY("CompressLevel", compressLevel),
136 };
137 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
138
139 return exports;
140 }
141 /**
142 * @brief CompressStrategy data initialization.
143 *
144 * @param env The environment that the Node-API call is invoked under.
145 * @param exports An empty object via the exports parameter as a convenience.
146 *
147 * @return The return value from Init is treated as the exports object for the module.
148 */
CompressStrategyInit(napi_env env,napi_value exports)149 napi_value CompressStrategyInit(napi_env env, napi_value exports)
150 {
151 APP_LOGD("%{public}s called.", __func__);
152 const int COMPRESS_STRATEGY_DEFAULT_STRATEGY = 0;
153 const int COMPRESS_STRATEGY_FILTERED = 1;
154 const int COMPRESS_STRATEGY_HUFFMAN_ONLY = 2;
155 const int COMPRESS_STRATEGY_RLE = 3;
156 const int COMPRESS_STRATEGY_FIXED = 4;
157
158 napi_value compressStrategy = nullptr;
159 napi_create_object(env, &compressStrategy);
160 SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_DEFAULT_STRATEGY", COMPRESS_STRATEGY_DEFAULT_STRATEGY);
161 SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_FILTERED", COMPRESS_STRATEGY_FILTERED);
162 SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_HUFFMAN_ONLY", COMPRESS_STRATEGY_HUFFMAN_ONLY);
163 SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_RLE", COMPRESS_STRATEGY_RLE);
164 SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_FIXED", COMPRESS_STRATEGY_FIXED);
165
166 napi_property_descriptor properties[] = {
167 DECLARE_NAPI_PROPERTY("CompressStrategy", compressStrategy),
168 };
169 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
170
171 return exports;
172 }
173 /**
174 * @brief MemLevel data initialization.
175 *
176 * @param env The environment that the Node-API call is invoked under.
177 * @param exports An empty object via the exports parameter as a convenience.
178 *
179 * @return The return value from Init is treated as the exports object for the module.
180 */
MemLevelInit(napi_env env,napi_value exports)181 napi_value MemLevelInit(napi_env env, napi_value exports)
182 {
183 APP_LOGD("%{public}s called.", __func__);
184 const int MEM_LEVEL_MIN = 1;
185 const int MEM_LEVEL_DEFAULT = 8;
186 const int MEM_LEVEL_MAX = 9;
187
188 napi_value memLevel = nullptr;
189 napi_create_object(env, &memLevel);
190 SetNamedProperty(env, memLevel, "MEM_LEVEL_MIN", MEM_LEVEL_MIN);
191 SetNamedProperty(env, memLevel, "MEM_LEVEL_DEFAULT", MEM_LEVEL_DEFAULT);
192 SetNamedProperty(env, memLevel, "MEM_LEVEL_MAX", MEM_LEVEL_MAX);
193
194 napi_property_descriptor properties[] = {
195 DECLARE_NAPI_PROPERTY("MemLevel", memLevel),
196 };
197 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
198
199 return exports;
200 }
201 /**
202 * @brief Errorcode data initialization.
203 *
204 * @param env The environment that the Node-API call is invoked under.
205 * @param exports An empty object via the exports parameter as a convenience.
206 *
207 * @return The return value from Init is treated as the exports object for the module.
208 */
ErrorCodeInit(napi_env env,napi_value exports)209 napi_value ErrorCodeInit(napi_env env, napi_value exports)
210 {
211 APP_LOGD("%{public}s called.", __func__);
212
213 const int ERROR_CODE_OK = 0;
214 const int ERROR_CODE_STREAM_END = 1;
215 const int ERROR_CODE_NEED_DICT = 2;
216 const int ERROR_CODE_ERRNO = -1;
217 const int ERROR_CODE_STREAM_ERROR = -2;
218 const int ERROR_CODE_DATA_ERROR = -3;
219 const int ERROR_CODE_MEM_ERROR = -4;
220 const int ERROR_CODE_BUF_ERROR = -5;
221 const int ERROR_CODE_VERSION_ERROR = -6;
222
223 napi_value errorCode = nullptr;
224 napi_create_object(env, &errorCode);
225 SetNamedProperty(env, errorCode, "ERROR_CODE_OK", ERROR_CODE_OK);
226 SetNamedProperty(env, errorCode, "ERROR_CODE_STREAM_END", ERROR_CODE_STREAM_END);
227 SetNamedProperty(env, errorCode, "ERROR_CODE_NEED_DICT", ERROR_CODE_NEED_DICT);
228 SetNamedProperty(env, errorCode, "ERROR_CODE_ERRNO", ERROR_CODE_ERRNO);
229 SetNamedProperty(env, errorCode, "ERROR_CODE_STREAM_ERROR", ERROR_CODE_STREAM_ERROR);
230 SetNamedProperty(env, errorCode, "ERROR_CODE_DATA_ERROR", ERROR_CODE_DATA_ERROR);
231 SetNamedProperty(env, errorCode, "ERROR_CODE_MEM_ERROR", ERROR_CODE_MEM_ERROR);
232 SetNamedProperty(env, errorCode, "ERROR_CODE_BUF_ERROR", ERROR_CODE_BUF_ERROR);
233 SetNamedProperty(env, errorCode, "ERROR_CODE_VERSION_ERROR", ERROR_CODE_VERSION_ERROR);
234
235 napi_property_descriptor properties[] = {
236 DECLARE_NAPI_PROPERTY("ErrorCode", errorCode),
237 };
238 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
239
240 return exports;
241 }
242
243 /**
244 * @brief FeatureAbility NAPI module registration.
245 *
246 * @param env The environment that the Node-API call is invoked under.
247 * @param exports An empty object via the exports parameter as a convenience.
248 *
249 * @return The return value from Init is treated as the exports object for the module.
250 */
ZlibInit(napi_env env,napi_value exports)251 napi_value ZlibInit(napi_env env, napi_value exports)
252 {
253 APP_LOGD("%{public}s,called", __func__);
254
255 napi_property_descriptor properties[] = {
256 DECLARE_NAPI_FUNCTION("zipFile", NAPI_ZipFile),
257 DECLARE_NAPI_FUNCTION("unzipFile", NAPI_UnzipFile),
258 DECLARE_NAPI_FUNCTION("compressFile", CompressFile),
259 DECLARE_NAPI_FUNCTION("decompressFile", DecompressFile),
260 };
261
262 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
263
264 return exports;
265 }
266
CreateZipAsyncCallbackInfo(napi_env env)267 AsyncZipCallbackInfo *CreateZipAsyncCallbackInfo(napi_env env)
268 {
269 APP_LOGD("%{public}s called.", __func__);
270 napi_status ret;
271 napi_value global = 0;
272 const napi_extended_error_info *errorInfo = nullptr;
273 ret = napi_get_global(env, &global);
274 if (ret != napi_ok) {
275 napi_get_last_error_info(env, &errorInfo);
276 if (errorInfo == nullptr) {
277 APP_LOGE("%{public}s errorInfo is null", __func__);
278 return nullptr;
279 }
280 APP_LOGE("%{public}s get_global=%{public}d err:%{public}s", __func__, ret, errorInfo->error_message);
281 }
282
283 AsyncZipCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncZipCallbackInfo {
284 .asyncWork = nullptr,
285 .zlibCallbackInfo = nullptr,
286 };
287 if (asyncCallbackInfo == nullptr) {
288 APP_LOGE("%{public}s asyncCallbackInfo is null", __func__);
289 return nullptr;
290 }
291 APP_LOGI("%{public}s end.", __func__);
292 return asyncCallbackInfo;
293 }
294
UnwrapStringParam(std::string & str,napi_env env,napi_value argv)295 napi_value UnwrapStringParam(std::string &str, napi_env env, napi_value argv)
296 {
297 APP_LOGD("%{public}s,called", __func__);
298 // unwrap the param[0]
299 napi_valuetype valueType = napi_valuetype::napi_undefined;
300 napi_status rev = napi_typeof(env, argv, &valueType);
301 if (rev != napi_ok) {
302 return nullptr;
303 }
304
305 if (valueType != napi_valuetype::napi_string) {
306 APP_LOGI("%{public}s called, Parameter type does not match", __func__);
307 return nullptr;
308 }
309
310 size_t len;
311 napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
312 if (status != napi_ok) {
313 APP_LOGI("%{public}s called, Get locale tag length failed", __func__);
314 return nullptr;
315 }
316 std::vector<char> buf(len + 1);
317 status = napi_get_value_string_utf8(env, argv, buf.data(), len + 1, &len);
318 if (status != napi_ok) {
319 APP_LOGI("%{public}s called, Get locale tag failed", __func__);
320 return nullptr;
321 }
322 str = std::string(buf.data());
323
324 napi_value result;
325 NAPI_CALL(env, napi_create_int32(env, 1, &result));
326 return result;
327 }
328
UnwrapOptionsParams(OPTIONS & options,napi_env env,napi_value arg)329 bool UnwrapOptionsParams(OPTIONS &options, napi_env env, napi_value arg)
330 {
331 APP_LOGD("%{public}s called.", __func__);
332
333 if (!IsTypeForNapiValue(env, arg, napi_object)) {
334 return false;
335 }
336 napi_valuetype jsValueType = napi_undefined;
337 napi_value jsProNameList = nullptr;
338 uint32_t jsProCount = 0;
339
340 NAPI_CALL_BASE(env, napi_get_property_names(env, arg, &jsProNameList), false);
341 NAPI_CALL_BASE(env, napi_get_array_length(env, jsProNameList, &jsProCount), false);
342 APP_LOGI("%{public}s called. Property size=%{public}d.", __func__, jsProCount);
343
344 napi_value jsProName = nullptr;
345 napi_value jsProValue = nullptr;
346
347 for (uint32_t index = 0; index < jsProCount; index++) {
348 NAPI_CALL_BASE(env, napi_get_element(env, jsProNameList, index, &jsProName), false);
349 std::string strProName = UnwrapStringFromJS(env, jsProName, std::string());
350 APP_LOGI("%{public}s called. Property name=%{public}s.", __func__, strProName.c_str());
351 NAPI_CALL_BASE(env, napi_get_named_property(env, arg, strProName.c_str(), &jsProValue), false);
352 NAPI_CALL_BASE(env, napi_typeof(env, jsProValue, &jsValueType), false);
353
354 int ret = 0;
355 if (strProName == std::string("flush")) {
356 NAPI_CALL_BASE_BOOL(UnwrapIntValue(env, jsProValue, ret), false);
357 options.flush = static_cast<FLUSH_TYPE>(ret);
358 } else if (strProName == std::string("finishFlush")) {
359 NAPI_CALL_BASE_BOOL(UnwrapIntValue(env, jsProValue, ret), false);
360 options.finishFlush = static_cast<FLUSH_TYPE>(ret);
361 } else if (strProName == std::string("chunkSize")) {
362 NAPI_CALL_BASE_BOOL(UnwrapIntValue(env, jsProValue, ret), false);
363 options.chunkSize = ret;
364 } else if (strProName == std::string("level")) {
365 NAPI_CALL_BASE_BOOL(UnwrapIntValue(env, jsProValue, ret), false);
366 COMPRESS_LEVE_CHECK(ret, false)
367 options.level = static_cast<COMPRESS_LEVEL>(ret);
368 } else if (strProName == std::string("memLevel")) {
369 NAPI_CALL_BASE_BOOL(UnwrapIntValue(env, jsProValue, ret), false);
370 COMPRESS_MEM_CHECK(ret, false)
371 options.memLevel = static_cast<MEMORY_LEVEL>(ret);
372 } else if (strProName == std::string("strategy")) {
373 NAPI_CALL_BASE_BOOL(UnwrapIntValue(env, jsProValue, ret), false);
374 COMPRESS_STRATEGY_CHECK(ret, false)
375 options.strategy = static_cast<COMPRESS_STRATEGY>(ret);
376 } else {
377 continue;
378 }
379 }
380 return true;
381 }
382
UnwrapZipParam(CallZipUnzipParam & param,napi_env env,napi_value * args,size_t argc)383 napi_value UnwrapZipParam(CallZipUnzipParam ¶m, napi_env env, napi_value *args, size_t argc)
384 {
385 APP_LOGD("%{public}s,called", __func__);
386 size_t argcPromise = 3;
387 if (argc < argcPromise) {
388 APP_LOGI("%{public}s called, param count is wrong", __func__);
389 return nullptr;
390 }
391
392 // unwrap the param[0]
393 if (UnwrapStringParam(param.src, env, args[0]) == nullptr) {
394 APP_LOGI("%{public}s called, args[0] error", __func__);
395 return nullptr;
396 }
397
398 // unwrap the param[1]
399 if (UnwrapStringParam(param.dest, env, args[1]) == nullptr) {
400 APP_LOGI("%{public}s called, args[1] error", __func__);
401 return nullptr;
402 }
403
404 // unwrap the param[2]
405 if (!UnwrapOptionsParams(param.options, env, args[2])) {
406 APP_LOGI("%{public}s called, args[2] error", __func__);
407 return nullptr;
408 }
409 // create reutrn
410 napi_value ret = 0;
411 NAPI_CALL_BASE(env, napi_create_int32(env, 0, &ret), nullptr);
412 return ret;
413 }
414
UnwrapUnZipParam(CallZipUnzipParam & param,napi_env env,napi_value * args,size_t argc)415 napi_value UnwrapUnZipParam(CallZipUnzipParam ¶m, napi_env env, napi_value *args, size_t argc)
416 {
417 APP_LOGD("%{public}s,called", __func__);
418 size_t argcPromise = 3;
419 if (argc < argcPromise) {
420 return nullptr;
421 }
422 // unwrap the param[0]
423 if (UnwrapStringParam(param.src, env, args[0]) == nullptr) {
424 return nullptr;
425 }
426
427 // unwrap the param[1]
428 if (UnwrapStringParam(param.dest, env, args[1]) == nullptr) {
429 return nullptr;
430 }
431
432 // create reutrn
433 napi_value ret = 0;
434 NAPI_CALL_BASE(env, napi_create_int32(env, 0, &ret), nullptr);
435 return ret;
436 }
437
438 /**
439 * @brief Zlib NAPI method : zipFile.
440 *
441 * @param env The environment that the Node-API call is invoked under.
442 * @param info The callback info passed into the callback function.
443 *
444 * @return The return value from NAPI C++ to JS for the module.
445 */
NAPI_ZipFile(napi_env env,napi_callback_info info)446 napi_value NAPI_ZipFile(napi_env env, napi_callback_info info)
447 {
448 APP_LOGD("%{public}s,called", __func__);
449 napi_value args[ARGS_MAX_COUNT] = {nullptr};
450 napi_value ret = 0;
451 size_t argcAsync = 4;
452 const size_t argcPromise = 3;
453 NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
454 if (argcAsync < argcPromise || argcAsync > ARGS_MAX_COUNT) {
455 APP_LOGE("%{public}s, Wrong argument count.", __func__);
456 return nullptr;
457 }
458
459 AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
460 if (asyncZipCallbackInfo == nullptr) {
461 return nullptr;
462 }
463
464 ret = ZipFileWrap(env, info, asyncZipCallbackInfo);
465 return ret;
466 }
467
ZipFileWrap(napi_env env,napi_callback_info info,AsyncZipCallbackInfo * asyncZipCallbackInfo)468 napi_value ZipFileWrap(napi_env env, napi_callback_info info, AsyncZipCallbackInfo *asyncZipCallbackInfo)
469 {
470 APP_LOGD("%{public}s,called", __func__);
471 napi_value args[ARGS_MAX_COUNT] = {nullptr};
472 napi_value thisArg = nullptr;
473 size_t argcAsync = 4;
474 const size_t argcPromise = 3;
475 NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisArg, nullptr));
476 if (argcAsync < argcPromise || argcAsync > ARGS_MAX_COUNT) {
477 APP_LOGE("%{public}s, Wrong argument count.", __func__);
478 return nullptr;
479 }
480 if (thisArg == nullptr) {
481 APP_LOGE("%{public}s, This argument is nullptr.", __func__);
482 return nullptr;
483 }
484 napi_valuetype valueTypeOfThis = napi_undefined;
485 NAPI_CALL_BASE(env, napi_typeof(env, thisArg, &valueTypeOfThis), nullptr);
486 if (valueTypeOfThis == napi_undefined) {
487 APP_LOGE("%{public}s, Wrong this value.", __func__);
488 return nullptr;
489 }
490
491 CallZipUnzipParam param;
492 if (UnwrapZipParam(param, env, args, argcAsync) == nullptr) {
493 APP_LOGE("%{public}s, call unwrapWant failed.", __func__);
494 return nullptr;
495 }
496 napi_value promise = nullptr;
497 std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
498 asyncZipCallbackInfo->param = param;
499 if (argcAsync > PARAM3) {
500 napi_valuetype valuetype = napi_undefined;
501 NAPI_CALL_BASE(env, napi_typeof(env, args[PARAM3], &valuetype), nullptr);
502 if (valuetype == napi_function) {
503 napi_ref callbackRef = nullptr;
504 napi_get_undefined(env, &promise);
505 napi_create_reference(env, args[PARAM3], 1, &callbackRef);
506 asyncZipCallbackInfo->zlibCallbackInfo =
507 std::make_shared<ZlibCallbackInfo>(env, callbackRef, nullptr, true);
508 } else {
509 return nullptr;
510 }
511 } else {
512 napi_deferred deferred;
513 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
514 asyncZipCallbackInfo->zlibCallbackInfo = std::make_shared<ZlibCallbackInfo>(env, nullptr, deferred, false);
515 }
516
517 std::shared_ptr<ZlibCallbackInfo>* cbInfo =
518 new std::shared_ptr<ZlibCallbackInfo>(asyncZipCallbackInfo->zlibCallbackInfo);
519 napi_wrap(env, thisArg, (void*)cbInfo, [](napi_env env, void* data, void* hint) {
520 std::shared_ptr<ZlibCallbackInfo>* cbInfo = static_cast<std::shared_ptr<ZlibCallbackInfo>*>(data);
521 if (cbInfo != nullptr && *cbInfo != nullptr) {
522 (*cbInfo)->SetValid(false);
523 delete cbInfo;
524 }
525 }, nullptr, nullptr);
526 CompressExcute(env, asyncZipCallbackInfo);
527 callbackPtr.release();
528 return promise;
529 }
530
531 /**
532 * @brief Zlib NAPI method : unzipFile.
533 *
534 * @param env The environment that the Node-API call is invoked under.
535 * @param info The callback info passed into the callback function.
536 *
537 * @return The return value from NAPI C++ to JS for the module.
538 */
NAPI_UnzipFile(napi_env env,napi_callback_info info)539 napi_value NAPI_UnzipFile(napi_env env, napi_callback_info info)
540 {
541 napi_value args[ARGS_MAX_COUNT] = {nullptr};
542 size_t argcAsync = 4;
543 size_t argcPromise = 3;
544 NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
545 if (argcAsync < argcPromise || argcAsync > ARGS_MAX_COUNT) {
546 APP_LOGE("%{public}s, Wrong argument count.", __func__);
547 return nullptr;
548 }
549 CallZipUnzipParam param;
550 if (UnwrapUnZipParam(param, env, args, argcAsync) == nullptr) {
551 APP_LOGE("%{public}s, call unwrap param failed.", __func__);
552 return nullptr;
553 }
554 AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
555 if (asyncZipCallbackInfo == nullptr) {
556 return nullptr;
557 }
558 std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
559 asyncZipCallbackInfo->param = param;
560 napi_value promise = nullptr;
561 if (argcAsync > PARAM3) {
562 napi_valuetype valuetype = napi_undefined;
563 NAPI_CALL_BASE(env, napi_typeof(env, args[PARAM3], &valuetype), nullptr);
564 if (valuetype == napi_function) {
565 napi_ref callbackRef = nullptr;
566 napi_get_undefined(env, &promise);
567 napi_create_reference(env, args[PARAM3], 1, &callbackRef);
568 asyncZipCallbackInfo->zlibCallbackInfo =
569 std::make_shared<ZlibCallbackInfo>(env, callbackRef, nullptr, true);
570 } else {
571 return nullptr;
572 }
573 } else {
574 napi_deferred deferred;
575 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
576 asyncZipCallbackInfo->zlibCallbackInfo = std::make_shared<ZlibCallbackInfo>(env, nullptr, deferred, false);
577 }
578 DecompressExcute(env, asyncZipCallbackInfo);
579 callbackPtr.release();
580 return promise;
581 }
582
583 // interface for v9
InitParam(CallZipUnzipParam & param,napi_env env,NapiArg & args,bool isZipFile)584 bool InitParam(CallZipUnzipParam ¶m, napi_env env, NapiArg &args, bool isZipFile)
585 {
586 if (args.GetMaxArgc() < PARAM3) {
587 return false;
588 }
589 for (size_t i = 0; i < PARAM3; ++i) {
590 napi_valuetype valueType = napi_undefined;
591 napi_typeof(env, args[i], &valueType);
592 if ((i == ARGS_POS_ZERO) && (valueType == napi_string)) {
593 if (UnwrapStringParam(param.src, env, args[i]) == nullptr) {
594 return false;
595 }
596 } else if ((i == ARGS_POS_ONE) && (valueType == napi_string)) {
597 if (UnwrapStringParam(param.dest, env, args[i]) == nullptr) {
598 return false;
599 }
600 } else if ((i == ARGS_POS_TWO) && (valueType == napi_object)) {
601 if (isZipFile && !UnwrapOptionsParams(param.options, env, args[i])) {
602 return false;
603 }
604 } else {
605 return false;
606 }
607 }
608 return true;
609 }
610
CompressExcute(napi_env env,AsyncZipCallbackInfo * asyncZipCallbackInfo)611 void CompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo)
612 {
613 if (asyncZipCallbackInfo == nullptr) {
614 APP_LOGE("asyncZipCallbackInfo is nullptr");
615 return;
616 }
617 std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
618 if (asyncZipCallbackInfo->zlibCallbackInfo == nullptr) {
619 APP_LOGE("zlibCallbackInfo is nullptr");
620 return;
621 }
622
623 Zip(asyncZipCallbackInfo->param.src, asyncZipCallbackInfo->param.dest,
624 false, asyncZipCallbackInfo->zlibCallbackInfo);
625 }
626
CompressFile(napi_env env,napi_callback_info info)627 napi_value CompressFile(napi_env env, napi_callback_info info)
628 {
629 APP_LOGD("napi begin CompressFile");
630 NapiArg args(env, info);
631 if (!args.Init(ARGS_SIZE_THREE, ARGS_SIZE_FOUR)) {
632 APP_LOGE("init args failed!");
633 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
634 return nullptr;
635 }
636 CallZipUnzipParam param;
637 if (!InitParam(param, env, args, true)) {
638 APP_LOGE("Init Param failed!");
639 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
640 return nullptr;
641 }
642 AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
643 if (asyncZipCallbackInfo == nullptr) {
644 APP_LOGE("asyncZipCallbackInfo nullptr!");
645 return nullptr;
646 }
647 asyncZipCallbackInfo->param = param;
648 std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
649 asyncZipCallbackInfo->zlibCallbackInfo =
650 std::make_shared<ZlibCallbackInfo>(env, nullptr, nullptr, false);
651 asyncZipCallbackInfo->zlibCallbackInfo->SetDeliverErrCode(true);
652 if (args.GetMaxArgc() > PARAM3) {
653 napi_valuetype valuetype = napi_undefined;
654 NAPI_CALL_BASE(env, napi_typeof(env, args[PARAM3], &valuetype), nullptr);
655 if (valuetype == napi_function) {
656 napi_ref callbackRef = nullptr;
657 NAPI_CALL(env, napi_create_reference(env, args[PARAM3], NAPI_RETURN_ONE, &callbackRef));
658 asyncZipCallbackInfo->zlibCallbackInfo->SetCallback(callbackRef);
659 asyncZipCallbackInfo->zlibCallbackInfo->SetIsCallback(true);
660 }
661 }
662 napi_value promise = nullptr;
663 if (!asyncZipCallbackInfo->zlibCallbackInfo->GetIsCallback()) {
664 napi_deferred deferred;
665 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
666 asyncZipCallbackInfo->zlibCallbackInfo->SetDeferred(deferred);
667 }
668 CompressExcute(env, asyncZipCallbackInfo);
669 callbackPtr.release();
670 return promise;
671 }
672
DecompressExcute(napi_env env,AsyncZipCallbackInfo * asyncZipCallbackInfo)673 void DecompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo)
674 {
675 if (asyncZipCallbackInfo == nullptr) {
676 APP_LOGE("asyncZipCallbackInfo is nullptr");
677 return;
678 }
679 std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
680 if (asyncZipCallbackInfo->zlibCallbackInfo == nullptr) {
681 APP_LOGE("zlibCallbackInfo is nullptr");
682 return;
683 }
684 Unzip(asyncZipCallbackInfo->param.src, asyncZipCallbackInfo->param.dest,
685 asyncZipCallbackInfo->param.options, asyncZipCallbackInfo->zlibCallbackInfo);
686 }
687
DecompressFile(napi_env env,napi_callback_info info)688 napi_value DecompressFile(napi_env env, napi_callback_info info)
689 {
690 APP_LOGD("napi begin CompressFile");
691 NapiArg args(env, info);
692 if (!args.Init(ARGS_SIZE_THREE, ARGS_SIZE_FOUR)) {
693 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
694 return nullptr;
695 }
696 CallZipUnzipParam param;
697 if (!InitParam(param, env, args, true)) {
698 BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
699 return nullptr;
700 }
701 AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
702 if (asyncZipCallbackInfo == nullptr) {
703 return nullptr;
704 }
705 asyncZipCallbackInfo->param = param;
706 std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
707 asyncZipCallbackInfo->zlibCallbackInfo =
708 std::make_shared<ZlibCallbackInfo>(env, nullptr, nullptr, false);
709 asyncZipCallbackInfo->zlibCallbackInfo->SetDeliverErrCode(true);
710 if (args.GetMaxArgc() > PARAM3) {
711 napi_valuetype valuetype = napi_undefined;
712 NAPI_CALL_BASE(env, napi_typeof(env, args[PARAM3], &valuetype), nullptr);
713 if (valuetype == napi_function) {
714 napi_ref callbackRef = nullptr;
715 NAPI_CALL(env, napi_create_reference(env, args[PARAM3], NAPI_RETURN_ONE, &callbackRef));
716 asyncZipCallbackInfo->zlibCallbackInfo->SetCallback(callbackRef);
717 asyncZipCallbackInfo->zlibCallbackInfo->SetIsCallback(true);
718 }
719 }
720 napi_value promise = nullptr;
721 if (!asyncZipCallbackInfo->zlibCallbackInfo->GetIsCallback()) {
722 napi_deferred deferred;
723 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
724 asyncZipCallbackInfo->zlibCallbackInfo->SetDeferred(deferred);
725 }
726 DecompressExcute(env, asyncZipCallbackInfo);
727 callbackPtr.release();
728 return promise;
729 }
730
731 } // namespace LIBZIP
732 } // namespace AppExecFwk
733 } // namespace OHOS
734