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