• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param, napi_env env, napi_value *args, size_t argc);
70 napi_value UnwrapUnZipParam(CallZipUnzipParam &param, 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 &param, 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 &param, 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 &param, 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