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 ¶m, napi_env env, napi_value *args, size_t argc);
93 napi_value UnwrapUnZipParam(CallZipUnzipParam ¶m, 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 ¶m, 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 ¶m, 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 ¶m, 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