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 constexpr int32_t PARAM2 = 2;
44 const char* WRONG_PARAM = "wrong param type";
45 const char* SRC_FILE = "inFile";
46 const std::string GET_ORIGINAL_SIZE = "GetOriginalSize";
47 }
48 
49 enum CompressFlushMode {
50     NO_FLUSH = 0,
51     PARTIAL_FLUSH,
52     SYNC_FLUSH,
53     FULL_FLUSH,
54     FINISH,
55     BLOCK,
56     TREES
57 };
58 
59 enum CompressMethod {
60     DEFLATED = 8
61 };
62 
63 enum ReturnStatus {
64     OK = 0,
65     STREAM_END = 1,
66     NEED_DICT = 2
67 };
68 
69 #define COMPRESS_LEVE_CHECK(level, ret)                                                            \
70     if (!(level == COMPRESS_LEVEL_NO_COMPRESSION || level == COMPRESS_LEVEL_DEFAULT_COMPRESSION || \
71             level == COMPRESS_LEVEL_BEST_SPEED || level == COMPRESS_LEVEL_BEST_COMPRESSION)) {     \
72         APP_LOGE("level parameter =[%{public}d] value is incorrect", static_cast<int>(level));     \
73         return ret;                                                                                \
74     }
75 
76 #define COMPRESS_STRATEGY_CHECK(strategy, false)                                                      \
77     if (!(strategy == COMPRESS_STRATEGY_DEFAULT_STRATEGY || strategy == COMPRESS_STRATEGY_FILTERED || \
78             strategy == COMPRESS_STRATEGY_HUFFMAN_ONLY || strategy == COMPRESS_STRATEGY_RLE ||        \
79             strategy == COMPRESS_STRATEGY_FIXED)) {                                                   \
80         APP_LOGE("strategy parameter= [%{public}d] value is incorrect", (int)strategy);            \
81         return ret;                                                                                   \
82     }
83 
84 #define COMPRESS_MEM_CHECK(mem, false)                                                                            \
85     if (!(mem == MEM_LEVEL_MIN_MEMLEVEL || mem == MEM_LEVEL_DEFAULT_MEMLEVEL || mem == MEM_LEVEL_MAX_MEMLEVEL)) { \
86         APP_LOGE("memLevel parameter =[%{public}d] value is incorrect", (int)mem);                             \
87         return ret;                                                                                               \
88     }
89 
90 void CompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo);
91 void DecompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo);
92 napi_value UnwrapZipParam(CallZipUnzipParam &param, napi_env env, napi_value *args, size_t argc);
93 napi_value UnwrapUnZipParam(CallZipUnzipParam &param, napi_env env, napi_value *args, size_t argc);
94 napi_value ZipFileWrap(napi_env env, napi_callback_info info, AsyncZipCallbackInfo *asyncZipCallbackInfo);
95 napi_value UnwrapStringParam(std::string &str, napi_env env, napi_value argv);
96 bool UnwrapOptionsParams(OPTIONS &options, napi_env env, napi_value arg);
97 
98 /**
99  * @brief FlushType data initialization.
100  *
101  * @param env The environment that the Node-API call is invoked under.
102  * @param exports An empty object via the exports parameter as a convenience.
103  *
104  * @return The return value from Init is treated as the exports object for the module.
105  */
FlushTypeInit(napi_env env,napi_value exports)106 napi_value FlushTypeInit(napi_env env, napi_value exports)
107 {
108     const int FLUSH_TYPE_NO_FLUSH = 0;
109     const int FLUSH_TYPE_PARTIAL_FLUSH = 1;
110     const int FLUSH_TYPE_SYNC_FLUSH = 2;
111     const int FLUSH_TYPE_FULL_FLUSH = 3;
112     const int FLUSH_TYPE_FINISH = 4;
113     const int FLUSH_TYPE_BLOCK = 5;
114     const int FLUSH_TYPE_TREES = 6;
115 
116     napi_value flushType = nullptr;
117     napi_create_object(env, &flushType);
118     SetNamedProperty(env, flushType, "FLUSH_TYPE_NO_FLUSH", FLUSH_TYPE_NO_FLUSH);
119     SetNamedProperty(env, flushType, "FLUSH_TYPE_PARTIAL_FLUSH", FLUSH_TYPE_PARTIAL_FLUSH);
120     SetNamedProperty(env, flushType, "FLUSH_TYPE_SYNC_FLUSH", FLUSH_TYPE_SYNC_FLUSH);
121     SetNamedProperty(env, flushType, "FLUSH_TYPE_FULL_FLUSH", FLUSH_TYPE_FULL_FLUSH);
122     SetNamedProperty(env, flushType, "FLUSH_TYPE_FINISH", FLUSH_TYPE_FINISH);
123     SetNamedProperty(env, flushType, "FLUSH_TYPE_BLOCK", FLUSH_TYPE_BLOCK);
124     SetNamedProperty(env, flushType, "FLUSH_TYPE_TREES", FLUSH_TYPE_TREES);
125 
126     napi_property_descriptor properties[] = {
127         DECLARE_NAPI_PROPERTY("FlushType", flushType),
128     };
129     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
130 
131     return exports;
132 }
133 /**
134  * @brief CompressLevel data initialization.
135  *
136  * @param env The environment that the Node-API call is invoked under.
137  * @param exports An empty object via the exports parameter as a convenience.
138  *
139  * @return The return value from Init is treated as the exports object for the module.
140  */
CompressLevelInit(napi_env env,napi_value exports)141 napi_value CompressLevelInit(napi_env env, napi_value exports)
142 {
143     const int COMPRESS_LEVEL_NO_COMPRESSION = 0;
144     const int COMPRESS_LEVEL_BEST_SPEED = 1;
145     const int COMPRESS_LEVEL_BEST_COMPRESSION = 9;
146     const int COMPRESS_LEVEL_DEFAULT_COMPRESSION = -1;
147 
148     napi_value compressLevel = nullptr;
149     napi_create_object(env, &compressLevel);
150     SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_NO_COMPRESSION", COMPRESS_LEVEL_NO_COMPRESSION);
151     SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_BEST_SPEED", COMPRESS_LEVEL_BEST_SPEED);
152     SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_BEST_COMPRESSION", COMPRESS_LEVEL_BEST_COMPRESSION);
153     SetNamedProperty(env, compressLevel, "COMPRESS_LEVEL_DEFAULT_COMPRESSION", COMPRESS_LEVEL_DEFAULT_COMPRESSION);
154 
155     napi_property_descriptor properties[] = {
156         DECLARE_NAPI_PROPERTY("CompressLevel", compressLevel),
157     };
158     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
159 
160     return exports;
161 }
162 /**
163  * @brief CompressFlushMode data initialization.
164  *
165  * @param env The environment that the Node-API call is invoked under.
166  * @param exports An empty object via the exports parameter as a convenience.
167  *
168  * @return The return value from Init is treated as the exports object for the module.
169  */
CompressFlushModeInit(napi_env env,napi_value exports)170 napi_value CompressFlushModeInit(napi_env env, napi_value exports)
171 {
172     napi_value CompressFlushMode = nullptr;
173     napi_create_object(env, &CompressFlushMode);
174     SetNamedProperty(env, CompressFlushMode, "NO_FLUSH", NO_FLUSH);
175     SetNamedProperty(env, CompressFlushMode, "PARTIAL_FLUSH", PARTIAL_FLUSH);
176     SetNamedProperty(env, CompressFlushMode, "SYNC_FLUSH", SYNC_FLUSH);
177     SetNamedProperty(env, CompressFlushMode, "FULL_FLUSH", FULL_FLUSH);
178     SetNamedProperty(env, CompressFlushMode, "FINISH", FINISH);
179     SetNamedProperty(env, CompressFlushMode, "BLOCK", BLOCK);
180     SetNamedProperty(env, CompressFlushMode, "TREES", TREES);
181     napi_property_descriptor properties[] = {
182         DECLARE_NAPI_PROPERTY("CompressFlushMode", CompressFlushMode),
183     };
184     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
185 
186     return exports;
187 }
188 /**
189  * @brief CompressMethodInit data initialization.
190  *
191  * @param env The environment that the Node-API call is invoked under.
192  * @param exports An empty object via the exports parameter as a convenience.
193  *
194  * @return The return value from Init is treated as the exports object for the module.
195  */
CompressMethodInit(napi_env env,napi_value exports)196 napi_value CompressMethodInit(napi_env env, napi_value exports)
197 {
198     napi_value CompressMethod = nullptr;
199     napi_create_object(env, &CompressMethod);
200     SetNamedProperty(env, CompressMethod, "DEFLATED", DEFLATED);
201     napi_property_descriptor properties[] = {
202         DECLARE_NAPI_PROPERTY("CompressMethod", CompressMethod),
203     };
204     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
205 
206     return exports;
207 }
208 /**
209  * @brief CompressStrategy data initialization.
210  *
211  * @param env The environment that the Node-API call is invoked under.
212  * @param exports An empty object via the exports parameter as a convenience.
213  *
214  * @return The return value from Init is treated as the exports object for the module.
215  */
CompressStrategyInit(napi_env env,napi_value exports)216 napi_value CompressStrategyInit(napi_env env, napi_value exports)
217 {
218     const int COMPRESS_STRATEGY_DEFAULT_STRATEGY = 0;
219     const int COMPRESS_STRATEGY_FILTERED = 1;
220     const int COMPRESS_STRATEGY_HUFFMAN_ONLY = 2;
221     const int COMPRESS_STRATEGY_RLE = 3;
222     const int COMPRESS_STRATEGY_FIXED = 4;
223 
224     napi_value compressStrategy = nullptr;
225     napi_create_object(env, &compressStrategy);
226     SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_DEFAULT_STRATEGY", COMPRESS_STRATEGY_DEFAULT_STRATEGY);
227     SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_FILTERED", COMPRESS_STRATEGY_FILTERED);
228     SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_HUFFMAN_ONLY", COMPRESS_STRATEGY_HUFFMAN_ONLY);
229     SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_RLE", COMPRESS_STRATEGY_RLE);
230     SetNamedProperty(env, compressStrategy, "COMPRESS_STRATEGY_FIXED", COMPRESS_STRATEGY_FIXED);
231 
232     napi_property_descriptor properties[] = {
233         DECLARE_NAPI_PROPERTY("CompressStrategy", compressStrategy),
234     };
235     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
236 
237     return exports;
238 }
239 /**
240  * @brief MemLevel data initialization.
241  *
242  * @param env The environment that the Node-API call is invoked under.
243  * @param exports An empty object via the exports parameter as a convenience.
244  *
245  * @return The return value from Init is treated as the exports object for the module.
246  */
MemLevelInit(napi_env env,napi_value exports)247 napi_value MemLevelInit(napi_env env, napi_value exports)
248 {
249     const int MEM_LEVEL_MIN = 1;
250     const int MEM_LEVEL_DEFAULT = 8;
251     const int MEM_LEVEL_MAX = 9;
252 
253     napi_value memLevel = nullptr;
254     napi_create_object(env, &memLevel);
255     SetNamedProperty(env, memLevel, "MEM_LEVEL_MIN", MEM_LEVEL_MIN);
256     SetNamedProperty(env, memLevel, "MEM_LEVEL_DEFAULT", MEM_LEVEL_DEFAULT);
257     SetNamedProperty(env, memLevel, "MEM_LEVEL_MAX", MEM_LEVEL_MAX);
258 
259     napi_property_descriptor properties[] = {
260         DECLARE_NAPI_PROPERTY("MemLevel", memLevel),
261     };
262     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
263 
264     return exports;
265 }
266 
267 /**
268  * @brief OffsetReferencePointInit data initialization.
269  *
270  * @param env The environment that the Node-API call is invoked under.
271  * @param exports An empty object via the exports parameter as a convenience.
272  *
273  * @return The return value from Init is treated as the exports object for the module.
274  */
OffsetReferencePointInit(napi_env env,napi_value exports)275 napi_value OffsetReferencePointInit(napi_env env, napi_value exports)
276 {
277     napi_value OffsetReferencePoint = nullptr;
278     napi_create_object(env, &OffsetReferencePoint);
279     SetNamedProperty(env, OffsetReferencePoint, "SEEK_SET", SEEK_SET);
280     SetNamedProperty(env, OffsetReferencePoint, "SEEK_CUR", SEEK_CUR);
281     napi_property_descriptor properties[] = {
282         DECLARE_NAPI_PROPERTY("OffsetReferencePoint", OffsetReferencePoint),
283     };
284     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
285 
286     return exports;
287 }
288 
289 /**
290  * @brief ReturnStatusInit data initialization.
291  *
292  * @param env The environment that the Node-API call is invoked under.
293  * @param exports An empty object via the exports parameter as a convenience.
294  *
295  * @return The return value from Init is treated as the exports object for the module.
296  */
ReturnStatusInit(napi_env env,napi_value exports)297 napi_value ReturnStatusInit(napi_env env, napi_value exports)
298 {
299     napi_value ReturnStatus = nullptr;
300     napi_create_object(env, &ReturnStatus);
301     SetNamedProperty(env, ReturnStatus, "OK", OK);
302     SetNamedProperty(env, ReturnStatus, "STREAM_END", STREAM_END);
303     SetNamedProperty(env, ReturnStatus, "NEED_DICT", NEED_DICT);
304     napi_property_descriptor properties[] = {
305         DECLARE_NAPI_PROPERTY("ReturnStatus", ReturnStatus),
306     };
307     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
308 
309     return exports;
310 }
311 
312 /**
313  * @brief Errorcode data initialization.
314  *
315  * @param env The environment that the Node-API call is invoked under.
316  * @param exports An empty object via the exports parameter as a convenience.
317  *
318  * @return The return value from Init is treated as the exports object for the module.
319  */
ErrorCodeInit(napi_env env,napi_value exports)320 napi_value ErrorCodeInit(napi_env env, napi_value exports)
321 {
322     const int ERROR_CODE_OK = 0;
323     const int ERROR_CODE_STREAM_END = 1;
324     const int ERROR_CODE_NEED_DICT = 2;
325     const int ERROR_CODE_ERRNO = -1;
326     const int ERROR_CODE_STREAM_ERROR = -2;
327     const int ERROR_CODE_DATA_ERROR = -3;
328     const int ERROR_CODE_MEM_ERROR = -4;
329     const int ERROR_CODE_BUF_ERROR = -5;
330     const int ERROR_CODE_VERSION_ERROR = -6;
331 
332     napi_value errorCode = nullptr;
333     napi_create_object(env, &errorCode);
334     SetNamedProperty(env, errorCode, "ERROR_CODE_OK", ERROR_CODE_OK);
335     SetNamedProperty(env, errorCode, "ERROR_CODE_STREAM_END", ERROR_CODE_STREAM_END);
336     SetNamedProperty(env, errorCode, "ERROR_CODE_NEED_DICT", ERROR_CODE_NEED_DICT);
337     SetNamedProperty(env, errorCode, "ERROR_CODE_ERRNO", ERROR_CODE_ERRNO);
338     SetNamedProperty(env, errorCode, "ERROR_CODE_STREAM_ERROR", ERROR_CODE_STREAM_ERROR);
339     SetNamedProperty(env, errorCode, "ERROR_CODE_DATA_ERROR", ERROR_CODE_DATA_ERROR);
340     SetNamedProperty(env, errorCode, "ERROR_CODE_MEM_ERROR", ERROR_CODE_MEM_ERROR);
341     SetNamedProperty(env, errorCode, "ERROR_CODE_BUF_ERROR", ERROR_CODE_BUF_ERROR);
342     SetNamedProperty(env, errorCode, "ERROR_CODE_VERSION_ERROR", ERROR_CODE_VERSION_ERROR);
343 
344     napi_property_descriptor properties[] = {
345         DECLARE_NAPI_PROPERTY("ErrorCode", errorCode),
346     };
347     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
348 
349     return exports;
350 }
351 
352 /**
353  * @brief FeatureAbility NAPI module registration.
354  *
355  * @param env The environment that the Node-API call is invoked under.
356  * @param exports An empty object via the exports parameter as a convenience.
357  *
358  * @return The return value from Init is treated as the exports object for the module.
359  */
ZlibInit(napi_env env,napi_value exports)360 napi_value ZlibInit(napi_env env, napi_value exports)
361 {
362     napi_property_descriptor properties[] = {
363         DECLARE_NAPI_FUNCTION("zipFile", NAPI_ZipFile),
364         DECLARE_NAPI_FUNCTION("unzipFile", NAPI_UnzipFile),
365         DECLARE_NAPI_FUNCTION("compressFile", CompressFile),
366         DECLARE_NAPI_FUNCTION("compressFiles", CompressFiles),
367         DECLARE_NAPI_FUNCTION("decompressFile", DecompressFile),
368         DECLARE_NAPI_FUNCTION("getOriginalSize", GetOriginalSize),
369     };
370 
371     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
372 
373     return exports;
374 }
375 
CreateZipAsyncCallbackInfo(napi_env env)376 AsyncZipCallbackInfo *CreateZipAsyncCallbackInfo(napi_env env)
377 {
378     napi_status ret;
379     napi_value global = 0;
380     const napi_extended_error_info *errorInfo = nullptr;
381     ret = napi_get_global(env, &global);
382     if (ret != napi_ok) {
383         napi_get_last_error_info(env, &errorInfo);
384         if (errorInfo == nullptr) {
385             APP_LOGE("errorInfo is null");
386             return nullptr;
387         }
388         APP_LOGE("get_global=%{public}d err:%{public}s", ret, errorInfo->error_message);
389     }
390 
391     AsyncZipCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncZipCallbackInfo {
392         .asyncWork = nullptr,
393         .zlibCallbackInfo = nullptr,
394     };
395     if (asyncCallbackInfo == nullptr) {
396         APP_LOGE("asyncCallbackInfo is null");
397         return nullptr;
398     }
399     return asyncCallbackInfo;
400 }
401 
UnwrapStringParam(std::string & str,napi_env env,napi_value argv)402 napi_value UnwrapStringParam(std::string &str, napi_env env, napi_value argv)
403 {
404     // unwrap the param[0]
405     napi_valuetype valueType = napi_valuetype::napi_undefined;
406     napi_status rev = napi_typeof(env, argv, &valueType);
407     if (rev != napi_ok) {
408         return nullptr;
409     }
410 
411     if (valueType != napi_valuetype::napi_string) {
412         APP_LOGI("Parameter type does not match");
413         return nullptr;
414     }
415 
416     size_t len;
417     napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
418     if (status != napi_ok) {
419         APP_LOGI("Get locale tag length failed");
420         return nullptr;
421     }
422     std::vector<char> buf(len + 1);
423     status = napi_get_value_string_utf8(env, argv, buf.data(), len + 1, &len);
424     if (status != napi_ok) {
425         APP_LOGI("Get locale tag failed");
426         return nullptr;
427     }
428     str = std::string(buf.data());
429 
430     napi_value result;
431     NAPI_CALL(env, napi_create_int32(env, 1, &result));
432     return result;
433 }
434 
UnwrapStringArrayParam(std::vector<std::string> & stringArray,napi_env env,napi_value argv)435 napi_value UnwrapStringArrayParam(std::vector<std::string> &stringArray, napi_env env, napi_value argv)
436 {
437     // unwrap the param[0]
438     napi_valuetype valueType = napi_valuetype::napi_undefined;
439     napi_status rev = napi_typeof(env, argv, &valueType);
440     if (rev != napi_ok) {
441         return nullptr;
442     }
443 
444     bool isArray = false;
445     if (napi_is_array(env, argv, &isArray) != napi_ok || !isArray) {
446         APP_LOGI("Parameter type does not match");
447         return nullptr;
448     }
449 
450     uint32_t size = 0U;
451     napi_status status = napi_get_array_length(env, argv, &size);
452     if (status != napi_ok || size == 0U) {
453         APP_LOGI("Get string array length failed");
454         return nullptr;
455     }
456 
457     napi_value result = nullptr;
458     for (uint32_t i = 0; i < size; i++) {
459         status = napi_get_element(env, argv, i, &result);
460         if (status != napi_ok) {
461             APP_LOGI("Get locale tag element failed");
462             return nullptr;
463         }
464         size_t strLen = 0;
465         status = napi_get_value_string_utf8(env, result, nullptr, 0, &strLen);
466         if (status != napi_ok) {
467             APP_LOGI("Get locale tag length failed");
468             return nullptr;
469         }
470 
471         std::vector<char> buf(strLen + 1);
472         status = napi_get_value_string_utf8(env, result, buf.data(), strLen + 1, &strLen);
473         if (status != napi_ok) {
474             APP_LOGI("Get locale tag failed");
475             return nullptr;
476         }
477         stringArray.push_back(std::string(buf.data()));
478     }
479 
480     result = nullptr;
481     NAPI_CALL(env, napi_create_int32(env, 1, &result));
482     return result;
483 }
484 
UnwrapOptionsParams(OPTIONS & options,napi_env env,napi_value arg)485 bool UnwrapOptionsParams(OPTIONS &options, napi_env env, napi_value arg)
486 {
487     if (!IsTypeForNapiValue(env, arg, napi_object)) {
488         return false;
489     }
490     napi_valuetype jsValueType = napi_undefined;
491     napi_value jsProNameList = nullptr;
492     uint32_t jsProCount = 0;
493 
494     NAPI_CALL_BASE(env, napi_get_property_names(env, arg, &jsProNameList), false);
495     NAPI_CALL_BASE(env, napi_get_array_length(env, jsProNameList, &jsProCount), false);
496 
497     napi_value jsProName = nullptr;
498     napi_value jsProValue = nullptr;
499 
500     for (uint32_t index = 0; index < jsProCount; index++) {
501         NAPI_CALL_BASE(env, napi_get_element(env, jsProNameList, index, &jsProName), false);
502         std::string strProName = UnwrapStringFromJS(env, jsProName, std::string());
503         APP_LOGD("Property name=%{public}s", strProName.c_str());
504         NAPI_CALL_BASE(env, napi_get_named_property(env, arg, strProName.c_str(), &jsProValue), false);
505         NAPI_CALL_BASE(env, napi_typeof(env, jsProValue, &jsValueType), false);
506 
507         int ret = 0;
508         if (strProName == std::string("flush")) {
509             if (UnwrapIntValue(env, jsProValue, ret)) {
510                 options.flush = static_cast<FLUSH_TYPE>(ret);
511             }
512         } else if (strProName == std::string("finishFlush")) {
513             if (UnwrapIntValue(env, jsProValue, ret)) {
514                 options.finishFlush = static_cast<FLUSH_TYPE>(ret);
515             }
516         } else if (strProName == std::string("chunkSize")) {
517             if (UnwrapIntValue(env, jsProValue, ret)) {
518                 options.chunkSize = ret;
519             }
520         } else if (strProName == std::string("level")) {
521             if (UnwrapIntValue(env, jsProValue, ret)) {
522                 COMPRESS_LEVE_CHECK(ret, false)
523                 options.level = static_cast<COMPRESS_LEVEL>(ret);
524             }
525         } else if (strProName == std::string("memLevel")) {
526             if (UnwrapIntValue(env, jsProValue, ret)) {
527                 COMPRESS_MEM_CHECK(ret, false)
528                 options.memLevel = static_cast<MEMORY_LEVEL>(ret);
529             }
530         } else if (strProName == std::string("strategy")) {
531             if (UnwrapIntValue(env, jsProValue, ret)) {
532                 COMPRESS_STRATEGY_CHECK(ret, false)
533                 options.strategy = static_cast<COMPRESS_STRATEGY>(ret);
534             }
535         }
536     }
537     return true;
538 }
539 
UnwrapZipParam(CallZipUnzipParam & param,napi_env env,napi_value * args,size_t argc)540 napi_value UnwrapZipParam(CallZipUnzipParam &param, napi_env env, napi_value *args, size_t argc)
541 {
542     size_t argcPromise = 3;
543     if (argc < argcPromise) {
544         APP_LOGI("param count is wrong");
545         return nullptr;
546     }
547 
548     // unwrap the param[0]
549     if (UnwrapStringParam(param.src, env, args[0]) == nullptr) {
550         APP_LOGI("src unwrap error");
551         return nullptr;
552     }
553 
554     // unwrap the param[1]
555     if (UnwrapStringParam(param.dest, env, args[1]) == nullptr) {
556         APP_LOGI("dest unwrap error");
557         return nullptr;
558     }
559 
560     // unwrap the param[2]
561     if (!UnwrapOptionsParams(param.options, env, args[2])) {
562         APP_LOGI("options unwrap error");
563         return nullptr;
564     }
565     // create reutrn
566     napi_value ret = 0;
567     NAPI_CALL_BASE(env, napi_create_int32(env, 0, &ret), nullptr);
568     return ret;
569 }
570 
UnwrapUnZipParam(CallZipUnzipParam & param,napi_env env,napi_value * args,size_t argc)571 napi_value UnwrapUnZipParam(CallZipUnzipParam &param, napi_env env, napi_value *args, size_t argc)
572 {
573     size_t argcPromise = 3;
574     if (argc < argcPromise) {
575         return nullptr;
576     }
577     // unwrap the param[0]
578     if (UnwrapStringParam(param.src, env, args[0]) == nullptr) {
579         return nullptr;
580     }
581 
582     // unwrap the param[1]
583     if (UnwrapStringParam(param.dest, env, args[1]) == nullptr) {
584         return nullptr;
585     }
586 
587     // create reutrn
588     napi_value ret = 0;
589     NAPI_CALL_BASE(env, napi_create_int32(env, 0, &ret), nullptr);
590     return ret;
591 }
592 
593 /**
594  * @brief Zlib NAPI method : zipFile.
595  *
596  * @param env The environment that the Node-API call is invoked under.
597  * @param info The callback info passed into the callback function.
598  *
599  * @return The return value from NAPI C++ to JS for the module.
600  */
NAPI_ZipFile(napi_env env,napi_callback_info info)601 napi_value NAPI_ZipFile(napi_env env, napi_callback_info info)
602 {
603     napi_value args[ARGS_MAX_COUNT] = {nullptr};
604     napi_value ret = 0;
605     size_t argcAsync = 4;
606     const size_t argcPromise = 3;
607     NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
608     if (argcAsync < argcPromise || argcAsync > ARGS_MAX_COUNT) {
609         APP_LOGE("Wrong argument count");
610         return nullptr;
611     }
612 
613     AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
614     if (asyncZipCallbackInfo == nullptr) {
615         return nullptr;
616     }
617 
618     ret = ZipFileWrap(env, info, asyncZipCallbackInfo);
619     return ret;
620 }
621 
ZipFileWrap(napi_env env,napi_callback_info info,AsyncZipCallbackInfo * asyncZipCallbackInfo)622 napi_value ZipFileWrap(napi_env env, napi_callback_info info, AsyncZipCallbackInfo *asyncZipCallbackInfo)
623 {
624     napi_value args[ARGS_MAX_COUNT] = {nullptr};
625     napi_value thisArg = nullptr;
626     size_t argcAsync = 4;
627     const size_t argcPromise = 3;
628     NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, &thisArg, nullptr));
629     if (argcAsync < argcPromise || argcAsync > ARGS_MAX_COUNT) {
630         APP_LOGE("Wrong argument count");
631         return nullptr;
632     }
633     if (thisArg == nullptr) {
634         APP_LOGE("thisArg is nullptr");
635         return nullptr;
636     }
637     napi_valuetype valueTypeOfThis = napi_undefined;
638     NAPI_CALL_BASE(env, napi_typeof(env, thisArg, &valueTypeOfThis), nullptr);
639     if (valueTypeOfThis == napi_undefined) {
640         APP_LOGE("Wrong this value");
641         return nullptr;
642     }
643 
644     CallZipUnzipParam param;
645     if (UnwrapZipParam(param, env, args, argcAsync) == nullptr) {
646         APP_LOGE("unwrapWant failed");
647         return nullptr;
648     }
649     napi_value promise = nullptr;
650     std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
651     asyncZipCallbackInfo->param = param;
652     if (argcAsync > 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_get_undefined(env,  &promise);
658             napi_create_reference(env, args[PARAM3], 1, &callbackRef);
659             asyncZipCallbackInfo->zlibCallbackInfo =
660                 std::make_shared<ZlibCallbackInfo>(env, callbackRef, nullptr, true);
661         }
662     } else {
663         napi_deferred deferred;
664         NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
665         asyncZipCallbackInfo->zlibCallbackInfo = std::make_shared<ZlibCallbackInfo>(env, nullptr, deferred, false);
666     }
667 
668     CompressExcute(env, asyncZipCallbackInfo);
669     callbackPtr.release();
670     return promise;
671 }
672 
673 /**
674  * @brief Zlib NAPI method : unzipFile.
675  *
676  * @param env The environment that the Node-API call is invoked under.
677  * @param info The callback info passed into the callback function.
678  *
679  * @return The return value from NAPI C++ to JS for the module.
680  */
NAPI_UnzipFile(napi_env env,napi_callback_info info)681 napi_value NAPI_UnzipFile(napi_env env, napi_callback_info info)
682 {
683     napi_value args[ARGS_MAX_COUNT] = {nullptr};
684     size_t argcAsync = 4;
685     size_t argcPromise = 3;
686     NAPI_CALL(env, napi_get_cb_info(env, info, &argcAsync, args, nullptr, nullptr));
687     if (argcAsync < argcPromise || argcAsync > ARGS_MAX_COUNT) {
688         APP_LOGE("Wrong argument count");
689         return nullptr;
690     }
691     CallZipUnzipParam param;
692     if (UnwrapUnZipParam(param, env, args, argcAsync) == nullptr) {
693         APP_LOGE("unwrap param failed");
694         return nullptr;
695     }
696     AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
697     if (asyncZipCallbackInfo == nullptr) {
698         return nullptr;
699     }
700     std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
701     asyncZipCallbackInfo->param = param;
702     napi_value promise = nullptr;
703     if (argcAsync > PARAM3) {
704         napi_valuetype valuetype = napi_undefined;
705         NAPI_CALL_BASE(env, napi_typeof(env, args[PARAM3], &valuetype), nullptr);
706         if (valuetype == napi_function) {
707             napi_ref callbackRef = nullptr;
708             napi_get_undefined(env,  &promise);
709             napi_create_reference(env, args[PARAM3], 1, &callbackRef);
710             asyncZipCallbackInfo->zlibCallbackInfo =
711                 std::make_shared<ZlibCallbackInfo>(env, callbackRef, nullptr, true);
712         }
713     } else {
714         napi_deferred deferred;
715         NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
716         asyncZipCallbackInfo->zlibCallbackInfo = std::make_shared<ZlibCallbackInfo>(env, nullptr, deferred, false);
717     }
718     DecompressExcute(env, asyncZipCallbackInfo);
719     callbackPtr.release();
720     return promise;
721 }
722 
723 // interface for v9
InitParam(CallZipUnzipParam & param,napi_env env,NapiArg & args,bool isZipFile)724 bool InitParam(CallZipUnzipParam &param, napi_env env, NapiArg &args, bool isZipFile)
725 {
726     if (args.GetMaxArgc() < PARAM2) {
727         return false;
728     }
729     for (size_t i = 0; i < args.GetMaxArgc(); ++i) {
730         napi_valuetype valueType = napi_undefined;
731         napi_typeof(env, args[i], &valueType);
732         if (i == ARGS_POS_ZERO) {
733             if (UnwrapStringParam(param.src, env, args[i]) == nullptr &&
734                 UnwrapStringArrayParam(param.srcFiles, env, args[i]) == nullptr) {
735                 return false;
736             }
737         } else if (i == ARGS_POS_ONE) {
738             if (UnwrapStringParam(param.dest, env, args[i]) == nullptr) {
739                 return false;
740             }
741         } else if (i == ARGS_POS_TWO) {
742             if (isZipFile && valueType != napi_function && !UnwrapOptionsParams(param.options, env, args[i])) {
743                 return false;
744             }
745         } else if (i == ARGS_POS_THREE) {
746             if (valueType == napi_function) {
747                 break;
748             }
749         } else {
750             return false;
751         }
752     }
753     return true;
754 }
755 
CompressExcute(napi_env env,AsyncZipCallbackInfo * asyncZipCallbackInfo)756 void CompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo)
757 {
758     if (asyncZipCallbackInfo == nullptr) {
759         APP_LOGE("asyncZipCallbackInfo is nullptr");
760         return;
761     }
762     std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
763     if (asyncZipCallbackInfo->zlibCallbackInfo == nullptr) {
764         APP_LOGE("zlibCallbackInfo is nullptr");
765         return;
766     }
767 
768     if (asyncZipCallbackInfo->param.srcFiles.size() > 0) {
769         Zips(asyncZipCallbackInfo->param.srcFiles,
770             asyncZipCallbackInfo->param.dest,
771             asyncZipCallbackInfo->param.options,
772             false,
773             asyncZipCallbackInfo->zlibCallbackInfo);
774     } else {
775         Zip(asyncZipCallbackInfo->param.src,
776             asyncZipCallbackInfo->param.dest,
777             asyncZipCallbackInfo->param.options,
778             false,
779             asyncZipCallbackInfo->zlibCallbackInfo);
780     }
781 }
782 
CompressFile(napi_env env,napi_callback_info info)783 napi_value CompressFile(napi_env env, napi_callback_info info)
784 {
785     APP_LOGD("napi begin CompressFile");
786     NapiArg args(env, info);
787     if (!args.Init(ARGS_SIZE_THREE, ARGS_SIZE_FOUR)) {
788         APP_LOGE("init args failed");
789         BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
790         return nullptr;
791     }
792     CallZipUnzipParam param;
793     if (!InitParam(param, env, args, true)) {
794         APP_LOGE("Init Param failed");
795         BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
796         return nullptr;
797     }
798     AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
799     if (asyncZipCallbackInfo == nullptr) {
800         APP_LOGE("asyncZipCallbackInfo nullptr");
801         return nullptr;
802     }
803     asyncZipCallbackInfo->param = param;
804     std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
805     asyncZipCallbackInfo->zlibCallbackInfo =
806                 std::make_shared<ZlibCallbackInfo>(env, nullptr, nullptr, false);
807     asyncZipCallbackInfo->zlibCallbackInfo->SetDeliverErrCode(true);
808     if (args.GetMaxArgc() > PARAM3) {
809         napi_valuetype valuetype = napi_undefined;
810         NAPI_CALL_BASE(env, napi_typeof(env, args[PARAM3], &valuetype), nullptr);
811         if (valuetype == napi_function) {
812             napi_ref callbackRef = nullptr;
813             NAPI_CALL(env, napi_create_reference(env, args[PARAM3], NAPI_RETURN_ONE, &callbackRef));
814             asyncZipCallbackInfo->zlibCallbackInfo->SetCallback(callbackRef);
815             asyncZipCallbackInfo->zlibCallbackInfo->SetIsCallback(true);
816         }
817     }
818     napi_value promise = nullptr;
819     if (!asyncZipCallbackInfo->zlibCallbackInfo->GetIsCallback()) {
820         napi_deferred deferred;
821         NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
822         asyncZipCallbackInfo->zlibCallbackInfo->SetDeferred(deferred);
823     }
824     CompressExcute(env, asyncZipCallbackInfo);
825     callbackPtr.release();
826     APP_LOGD("napi end CompressFile");
827     return promise;
828 }
829 
CompressFiles(napi_env env,napi_callback_info info)830 napi_value CompressFiles(napi_env env, napi_callback_info info)
831 {
832     return CompressFile(env, info);
833 }
834 
DecompressExcute(napi_env env,AsyncZipCallbackInfo * asyncZipCallbackInfo)835 void DecompressExcute(napi_env env, AsyncZipCallbackInfo *asyncZipCallbackInfo)
836 {
837     if (asyncZipCallbackInfo == nullptr) {
838         APP_LOGE("asyncZipCallbackInfo is nullptr");
839         return;
840     }
841     std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
842     if (asyncZipCallbackInfo->zlibCallbackInfo == nullptr) {
843         APP_LOGE("zlibCallbackInfo is nullptr");
844         return;
845     }
846     Unzip(asyncZipCallbackInfo->param.src, asyncZipCallbackInfo->param.dest,
847         asyncZipCallbackInfo->param.options, asyncZipCallbackInfo->zlibCallbackInfo);
848 }
849 
DecompressFile(napi_env env,napi_callback_info info)850 napi_value DecompressFile(napi_env env, napi_callback_info info)
851 {
852     APP_LOGD("napi begin CompressFile");
853     NapiArg args(env, info);
854     if (!args.Init(ARGS_SIZE_TWO, ARGS_SIZE_FOUR)) {
855         BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
856         return nullptr;
857     }
858     CallZipUnzipParam param;
859     if (!InitParam(param, env, args, true)) {
860         BusinessError::ThrowError(env, ERROR_PARAM_CHECK_ERROR, WRONG_PARAM);
861         return nullptr;
862     }
863     AsyncZipCallbackInfo *asyncZipCallbackInfo = CreateZipAsyncCallbackInfo(env);
864     if (asyncZipCallbackInfo == nullptr) {
865         return nullptr;
866     }
867     asyncZipCallbackInfo->param = param;
868     std::unique_ptr<AsyncZipCallbackInfo> callbackPtr {asyncZipCallbackInfo};
869     asyncZipCallbackInfo->zlibCallbackInfo =
870                 std::make_shared<ZlibCallbackInfo>(env, nullptr, nullptr, false);
871     asyncZipCallbackInfo->zlibCallbackInfo->SetDeliverErrCode(true);
872     for (size_t i = PARAM2; i < args.GetMaxArgc(); i++) {
873         napi_valuetype valuetype = napi_undefined;
874         NAPI_CALL_BASE(env, napi_typeof(env, args[i], &valuetype), nullptr);
875         if (valuetype == napi_function) {
876             napi_ref callbackRef = nullptr;
877             NAPI_CALL(env, napi_create_reference(env, args[i], NAPI_RETURN_ONE, &callbackRef));
878             asyncZipCallbackInfo->zlibCallbackInfo->SetCallback(callbackRef);
879             asyncZipCallbackInfo->zlibCallbackInfo->SetIsCallback(true);
880             break;
881         }
882     }
883     napi_value promise = nullptr;
884     if (!asyncZipCallbackInfo->zlibCallbackInfo->GetIsCallback()) {
885         napi_deferred deferred;
886         NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
887         asyncZipCallbackInfo->zlibCallbackInfo->SetDeferred(deferred);
888     }
889     DecompressExcute(env, asyncZipCallbackInfo);
890     callbackPtr.release();
891     return promise;
892 }
893 
GetOriginalSizeExec(napi_env env,void * data)894 void GetOriginalSizeExec(napi_env env, void *data)
895 {
896     APP_LOGD("NAPI begin GetOriginalSizeExec");
897     OriginalSizeCallbackInfo *asyncCallbackInfo = reinterpret_cast<OriginalSizeCallbackInfo *>(data);
898     if (asyncCallbackInfo == nullptr) {
899         APP_LOGE("asyncCallbackInfo is null");
900         return;
901     }
902     asyncCallbackInfo->err =
903         GetOriginalSize(asyncCallbackInfo->srcFile, asyncCallbackInfo->originalSize);
904     APP_LOGD("GetOriginalSizeExec end");
905 }
906 
GetOriginalSizeComplete(napi_env env,napi_status status,void * data)907 void GetOriginalSizeComplete(napi_env env, napi_status status, void *data)
908 {
909     APP_LOGD("NAPI begin GetOriginalSizeComplete");
910     OriginalSizeCallbackInfo *asyncCallbackInfo = reinterpret_cast<OriginalSizeCallbackInfo *>(data);
911     if (asyncCallbackInfo == nullptr) {
912         APP_LOGE("asyncCallbackInfo is null");
913         return;
914     }
915     std::unique_ptr<OriginalSizeCallbackInfo> callbackPtr {asyncCallbackInfo};
916     napi_value result[ARGS_SIZE_TWO] = {0};
917     if (asyncCallbackInfo->err != ERR_OK) {
918         ErrCode errCode = CommonFunc::ConvertErrCode(asyncCallbackInfo->err);
919         APP_LOGD("ErrCode is %{public}d - %{public}d", errCode, asyncCallbackInfo->err);
920         result[0] = BusinessError::CreateCommonError(env, errCode, GET_ORIGINAL_SIZE);
921         NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &result[1]));
922     } else {
923         result[0] = BusinessError::CreateCommonError(env, ERR_OK, "");
924         NAPI_CALL_RETURN_VOID(env, napi_create_int64(env, asyncCallbackInfo->originalSize, &result[1]));
925     }
926     CommonFunc::NapiReturnDeferred<OriginalSizeCallbackInfo>(env, asyncCallbackInfo, result, ARGS_SIZE_TWO);
927     APP_LOGD("GetOriginalSizeComplete end");
928 }
929 
GetOriginalSize(napi_env env,napi_callback_info info)930 napi_value GetOriginalSize(napi_env env, napi_callback_info info)
931 {
932     APP_LOGD("NAPI begin GetOriginalSize");
933     OriginalSizeCallbackInfo *asyncCallbackInfo = new (std::nothrow) OriginalSizeCallbackInfo(env);
934     if (asyncCallbackInfo == nullptr) {
935         APP_LOGE("asyncCallbackInfo is null");
936         return nullptr;
937     }
938     std::unique_ptr<OriginalSizeCallbackInfo> callbackPtr {asyncCallbackInfo};
939     asyncCallbackInfo->err = ERR_OK;
940     NapiArg args(env, info);
941     if (!args.Init(ARGS_SIZE_ONE, ARGS_SIZE_TWO)) {
942         APP_LOGE("parameters init failed");
943         BusinessError::ThrowTooFewParametersError(env, ERROR_PARAM_CHECK_ERROR);
944         return nullptr;
945     }
946     if (!CommonFunc::ParseString(env, args[ARGS_POS_ZERO], asyncCallbackInfo->srcFile)) {
947         APP_LOGE("srcFile parse failed");
948         BusinessError::ThrowParameterTypeError(env, ERROR_PARAM_CHECK_ERROR, SRC_FILE, TYPE_STRING);
949         return nullptr;
950     }
951     auto promise = CommonFunc::AsyncCallNativeMethod<OriginalSizeCallbackInfo>(env,
952         asyncCallbackInfo, GET_ORIGINAL_SIZE, GetOriginalSizeExec, GetOriginalSizeComplete);
953     callbackPtr.release();
954     APP_LOGD("NAPI end");
955     return promise;
956 }
957 }  // namespace LIBZIP
958 }  // namespace AppExecFwk
959 }  // namespace OHOS
960