• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 
16 #include "ani_signature_builder.h"
17 #include "ani_zlib_callback_info.h"
18 #include "business_error_ani.h"
19 #include "common_fun_ani.h"
20 #include "common_func.h"
21 #include "enum_util.h"
22 #include "napi_constants.h"
23 #include "zip.h"
24 #include "zlib.h"
25 
26 namespace OHOS {
27 namespace AppExecFwk {
28 
29 namespace {
30 constexpr const char* NS_NAME_ZLIB = "@ohos.zlib.zlib";
31 constexpr const char* PROPERTY_NAME_LEVEL = "level";
32 constexpr const char* PROPERTY_NAME_MEMLEVEL = "memLevel";
33 constexpr const char* PROPERTY_NAME_STRATEGY = "strategy";
34 constexpr const char* PROPERTY_NAME_PARALLEL = "parallel";
35 constexpr const char* TYPE_NAME_CHECKSUMINTERNAL = "ChecksumInternal";
36 constexpr const char* PARAM_NAME_IN_FILE = "inFile";
37 constexpr const char* PARAM_NAME_IN_FILES = "inFiles";
38 constexpr const char* PARAM_NAME_OUT_FILE = "outFile";
39 constexpr const char* PARAM_NAME_OPTIONS = "options";
40 constexpr const char* PARAM_NAME_BUF = "buf";
41 constexpr const char* PARAM_NAME_ADLER = "adler";
42 constexpr const char* PARAM_NAME_ADLER1 = "adler1";
43 constexpr const char* PARAM_NAME_ADLER2 = "adler2";
44 constexpr const char* PARAM_NAME_CRC = "crc";
45 constexpr const char* PARAM_NAME_CRC1 = "crc1";
46 constexpr const char* PARAM_NAME_CRC2 = "crc2";
47 constexpr const char* PARAM_NAME_LEN2 = "len2";
48 constexpr const char* TYPE_ARRAYBUFFER = "ArrayBuffer";
49 constexpr const size_t TABLE_SIZE = 256;
50 constexpr int32_t SHIFT_AMOUNT = 8;
51 constexpr uint64_t CRC64_TABLE[] = {
52     0x0000000000000000, 0x3c3b78e888d80fe1, 0x7876f1d111b01fc2, 0x444d893999681023,
53     0x750c207570b452a3, 0x4937589df86c5d42, 0x0d7ad1a461044d61, 0x3141a94ce9dc4280,
54     0x6ff9833db2bcc861, 0x53c2fbd53a64c780, 0x178f72eca30cd7a3, 0x2bb40a042bd4d842,
55     0x1af5a348c2089ac2, 0x26cedba04ad09523, 0x62835299d3b88500, 0x5eb82a715b608ae1,
56     0x5a12c5ac36adfde5, 0x6629bd44be75f204, 0x2264347d271de227, 0x1e5f4c95afc5edc6,
57     0x2f1ee5d94619af46, 0x13259d31cec1a0a7, 0x5768140857a9b084, 0x6b536ce0df71bf65,
58     0x35eb469184113584, 0x09d03e790cc93a65, 0x4d9db74095a12a46, 0x71a6cfa81d7925a7,
59     0x40e766e4f4a56727, 0x7cdc1e0c7c7d68c6, 0x38919735e51578e5, 0x04aaefdd6dcd7704,
60     0x31c4488f3e8f96ed, 0x0dff3067b657990c, 0x49b2b95e2f3f892f, 0x7589c1b6a7e786ce,
61     0x44c868fa4e3bc44e, 0x78f31012c6e3cbaf, 0x3cbe992b5f8bdb8c, 0x0085e1c3d753d46d,
62     0x5e3dcbb28c335e8c, 0x6206b35a04eb516d, 0x264b3a639d83414e, 0x1a70428b155b4eaf,
63     0x2b31ebc7fc870c2f, 0x170a932f745f03ce, 0x53471a16ed3713ed, 0x6f7c62fe65ef1c0c,
64     0x6bd68d2308226b08, 0x57edf5cb80fa64e9, 0x13a07cf2199274ca, 0x2f9b041a914a7b2b,
65     0x1edaad56789639ab, 0x22e1d5bef04e364a, 0x66ac5c8769262669, 0x5a97246fe1fe2988,
66     0x042f0e1eba9ea369, 0x381476f63246ac88, 0x7c59ffcfab2ebcab, 0x4062872723f6b34a,
67     0x71232e6bca2af1ca, 0x4d18568342f2fe2b, 0x0955dfbadb9aee08, 0x356ea7525342e1e9,
68     0x6388911e7d1f2dda, 0x5fb3e9f6f5c7223b, 0x1bfe60cf6caf3218, 0x27c51827e4773df9,
69     0x1684b16b0dab7f79, 0x2abfc98385737098, 0x6ef240ba1c1b60bb, 0x52c9385294c36f5a,
70     0x0c711223cfa3e5bb, 0x304a6acb477bea5a, 0x7407e3f2de13fa79, 0x483c9b1a56cbf598,
71     0x797d3256bf17b718, 0x45464abe37cfb8f9, 0x010bc387aea7a8da, 0x3d30bb6f267fa73b,
72     0x399a54b24bb2d03f, 0x05a12c5ac36adfde, 0x41eca5635a02cffd, 0x7dd7dd8bd2dac01c,
73     0x4c9674c73b06829c, 0x70ad0c2fb3de8d7d, 0x34e085162ab69d5e, 0x08dbfdfea26e92bf,
74     0x5663d78ff90e185e, 0x6a58af6771d617bf, 0x2e15265ee8be079c, 0x122e5eb66066087d,
75     0x236ff7fa89ba4afd, 0x1f548f120162451c, 0x5b19062b980a553f, 0x67227ec310d25ade,
76     0x524cd9914390bb37, 0x6e77a179cb48b4d6, 0x2a3a28405220a4f5, 0x160150a8daf8ab14,
77     0x2740f9e43324e994, 0x1b7b810cbbfce675, 0x5f3608352294f656, 0x630d70ddaa4cf9b7,
78     0x3db55aacf12c7356, 0x018e224479f47cb7, 0x45c3ab7de09c6c94, 0x79f8d39568446375,
79     0x48b97ad9819821f5, 0x7482023109402e14, 0x30cf8b0890283e37, 0x0cf4f3e018f031d6,
80     0x085e1c3d753d46d2, 0x346564d5fde54933, 0x7028edec648d5910, 0x4c139504ec5556f1,
81     0x7d523c4805891471, 0x416944a08d511b90, 0x0524cd9914390bb3, 0x391fb5719ce10452,
82     0x67a79f00c7818eb3, 0x5b9ce7e84f598152, 0x1fd16ed1d6319171, 0x23ea16395ee99e90,
83     0x12abbf75b735dc10, 0x2e90c79d3fedd3f1, 0x6add4ea4a685c3d2, 0x56e6364c2e5dcc33,
84     0x42f0e1eba9ea3693, 0x7ecb990321323972, 0x3a86103ab85a2951, 0x06bd68d2308226b0,
85     0x37fcc19ed95e6430, 0x0bc7b97651866bd1, 0x4f8a304fc8ee7bf2, 0x73b148a740367413,
86     0x2d0962d61b56fef2, 0x11321a3e938ef113, 0x557f93070ae6e130, 0x6944ebef823eeed1,
87     0x580542a36be2ac51, 0x643e3a4be33aa3b0, 0x2073b3727a52b393, 0x1c48cb9af28abc72,
88     0x18e224479f47cb76, 0x24d95caf179fc497, 0x6094d5968ef7d4b4, 0x5cafad7e062fdb55,
89     0x6dee0432eff399d5, 0x51d57cda672b9634, 0x1598f5e3fe438617, 0x29a38d0b769b89f6,
90     0x771ba77a2dfb0317, 0x4b20df92a5230cf6, 0x0f6d56ab3c4b1cd5, 0x33562e43b4931334,
91     0x0217870f5d4f51b4, 0x3e2cffe7d5975e55, 0x7a6176de4cff4e76, 0x465a0e36c4274197,
92     0x7334a9649765a07e, 0x4f0fd18c1fbdaf9f, 0x0b4258b586d5bfbc, 0x3779205d0e0db05d,
93     0x06388911e7d1f2dd, 0x3a03f1f96f09fd3c, 0x7e4e78c0f661ed1f, 0x427500287eb9e2fe,
94     0x1ccd2a5925d9681f, 0x20f652b1ad0167fe, 0x64bbdb88346977dd, 0x5880a360bcb1783c,
95     0x69c10a2c556d3abc, 0x55fa72c4ddb5355d, 0x11b7fbfd44dd257e, 0x2d8c8315cc052a9f,
96     0x29266cc8a1c85d9b, 0x151d14202910527a, 0x51509d19b0784259, 0x6d6be5f138a04db8,
97     0x5c2a4cbdd17c0f38, 0x6011345559a400d9, 0x245cbd6cc0cc10fa, 0x1867c58448141f1b,
98     0x46dfeff5137495fa, 0x7ae4971d9bac9a1b, 0x3ea91e2402c48a38, 0x029266cc8a1c85d9,
99     0x33d3cf8063c0c759, 0x0fe8b768eb18c8b8, 0x4ba53e517270d89b, 0x779e46b9faa8d77a,
100     0x217870f5d4f51b49, 0x1d43081d5c2d14a8, 0x590e8124c545048b, 0x6535f9cc4d9d0b6a,
101     0x54745080a44149ea, 0x684f28682c99460b, 0x2c02a151b5f15628, 0x1039d9b93d2959c9,
102     0x4e81f3c86649d328, 0x72ba8b20ee91dcc9, 0x36f7021977f9ccea, 0x0acc7af1ff21c30b,
103     0x3b8dd3bd16fd818b, 0x07b6ab559e258e6a, 0x43fb226c074d9e49, 0x7fc05a848f9591a8,
104     0x7b6ab559e258e6ac, 0x4751cdb16a80e94d, 0x031c4488f3e8f96e, 0x3f273c607b30f68f,
105     0x0e66952c92ecb40f, 0x325dedc41a34bbee, 0x761064fd835cabcd, 0x4a2b1c150b84a42c,
106     0x1493366450e42ecd, 0x28a84e8cd83c212c, 0x6ce5c7b54154310f, 0x50debf5dc98c3eee,
107     0x619f161120507c6e, 0x5da46ef9a888738f, 0x19e9e7c031e063ac, 0x25d29f28b9386c4d,
108     0x10bc387aea7a8da4, 0x2c87409262a28245, 0x68cac9abfbca9266, 0x54f1b14373129d87,
109     0x65b0180f9acedf07, 0x598b60e71216d0e6, 0x1dc6e9de8b7ec0c5, 0x21fd913603a6cf24,
110     0x7f45bb4758c645c5, 0x437ec3afd01e4a24, 0x07334a9649765a07, 0x3b08327ec1ae55e6,
111     0x0a499b3228721766, 0x3672e3daa0aa1887, 0x723f6ae339c208a4, 0x4e04120bb11a0745,
112     0x4aaefdd6dcd77041, 0x7695853e540f7fa0, 0x32d80c07cd676f83, 0x0ee374ef45bf6062,
113     0x3fa2dda3ac6322e2, 0x0399a54b24bb2d03, 0x47d42c72bdd33d20, 0x7bef549a350b32c1,
114     0x25577eeb6e6bb820, 0x196c0603e6b3b7c1, 0x5d218f3a7fdba7e2, 0x611af7d2f703a803,
115     0x505b5e9e1edfea83, 0x6c6026769607e562, 0x282daf4f0f6ff541, 0x1416d7a787b7faa0
116 };
117 } // namespace
118 
119 using namespace arkts::ani_signature;
120 
ComputeCrc64(uint64_t initCrc,const char * data,size_t length)121 static uint64_t ComputeCrc64(uint64_t initCrc, const char *data, size_t length)
122 {
123     uint64_t crc = initCrc;
124 
125     /* computation of the CRC */
126     for (size_t i = 0; i < length; ++i) {
127         crc = CRC64_TABLE[(crc ^ data[i]) & 0xFF] ^ (crc >> SHIFT_AMOUNT);
128     }
129 
130     return crc;
131 }
132 
133 template<typename tableType>
ConvertCRCTable(ani_env * env,const tableType * table,const size_t tableSize)134 static ani_object ConvertCRCTable(ani_env* env, const tableType* table, const size_t tableSize)
135 {
136     Type arrayType = Builder::BuildClass("escompat.Array");
137     ani_class arrayCls = CommonFunAni::CreateClassByName(env, arrayType.Descriptor());
138     RETURN_NULL_IF_NULL(arrayCls);
139 
140     ani_method arrayCtor = nullptr;
141     ani_status status = env->Class_FindMethod(arrayCls, Builder::BuildConstructorName().c_str(),
142         Builder::BuildSignatureDescriptor({ Builder::BuildInt() }).c_str(), &arrayCtor);
143     if (status != ANI_OK) {
144         APP_LOGE("Class_FindMethod Array failed %{public}d", status);
145         return nullptr;
146     }
147 
148     ani_object arrayObj = nullptr;
149     status = env->Object_New(arrayCls, arrayCtor, &arrayObj, tableSize);
150     if (status != ANI_OK) {
151         APP_LOGE("Object_New Array failed %{public}d", status);
152         return nullptr;
153     }
154 
155     Type doubleType = Builder::BuildClass("std.core.Double");
156     ani_class doubleClass = nullptr;
157     status = env->FindClass(doubleType.Descriptor().c_str(), &doubleClass);
158     if (status != ANI_OK) {
159         APP_LOGE("FindClass Double failed %{public}d", status);
160         return nullptr;
161     }
162     ani_method doubleCtor = nullptr;
163     status = env->Class_FindMethod(doubleClass, Builder::BuildConstructorName().c_str(),
164         Builder::BuildSignatureDescriptor({ Builder::BuildDouble() }).c_str(), &doubleCtor);
165     if (status != ANI_OK) {
166         APP_LOGE("Class_FindMethod Double ctor failed %{public}d", status);
167         return nullptr;
168     }
169     std::string setSig = Builder::BuildSignatureDescriptor({ Builder::BuildInt(), Builder::BuildNull() });
170 
171     for (size_t i = 0; i < tableSize; ++i) {
172         ani_object doubleObj = nullptr;
173         status = env->Object_New(doubleClass, doubleCtor, &doubleObj, static_cast<double>(table[i]));
174         if (status != ANI_OK) {
175             APP_LOGE("Object_New Double failed %{public}d", status);
176             return nullptr;
177         }
178         status = env->Object_CallMethodByName_Void(arrayObj, "$_set", setSig.c_str(), i, doubleObj);
179         env->Reference_Delete(doubleObj);
180         if (status != ANI_OK) {
181             APP_LOGE("Object_CallMethodByName_Void failed %{public}d", status);
182             return nullptr;
183         }
184     }
185 
186     return arrayObj;
187 }
188 
ANIParseOptions(ani_env * env,ani_object object,LIBZIP::OPTIONS & options)189 static bool ANIParseOptions(ani_env* env, ani_object object, LIBZIP::OPTIONS& options)
190 {
191     RETURN_FALSE_IF_NULL(env);
192     RETURN_FALSE_IF_NULL(object);
193 
194     ani_enum_item enumItem = nullptr;
195     // level?: CompressLevel
196     if (CommonFunAni::CallGetterOptional(env, object, PROPERTY_NAME_LEVEL, &enumItem)) {
197         RETURN_FALSE_IF_FALSE(EnumUtils::EnumETSToNative(env, enumItem, options.level));
198     }
199 
200     // memLevel?: MemLevel
201     if (CommonFunAni::CallGetterOptional(env, object, PROPERTY_NAME_MEMLEVEL, &enumItem)) {
202         RETURN_FALSE_IF_FALSE(EnumUtils::EnumETSToNative(env, enumItem, options.memLevel));
203     }
204 
205     // strategy?: CompressStrategy
206     if (CommonFunAni::CallGetterOptional(env, object, PROPERTY_NAME_STRATEGY, &enumItem)) {
207         RETURN_FALSE_IF_FALSE(EnumUtils::EnumETSToNative(env, enumItem, options.strategy));
208     }
209 
210     // parallel?: ParallelStrategy
211     if (CommonFunAni::CallGetterOptional(env, object, PROPERTY_NAME_PARALLEL, &enumItem)) {
212         RETURN_FALSE_IF_FALSE(EnumUtils::EnumETSToNative(env, enumItem, options.parallel));
213     }
214 
215     return true;
216 }
217 
CompressFile(ani_env * env,ani_string aniInFile,ani_string aniOutFile,ani_object aniOptions)218 static void CompressFile(ani_env* env, ani_string aniInFile, ani_string aniOutFile, ani_object aniOptions)
219 {
220     RETURN_IF_NULL(env);
221     RETURN_IF_NULL(aniInFile);
222     RETURN_IF_NULL(aniOutFile);
223     RETURN_IF_NULL(aniOptions);
224 
225     std::string inFile;
226     if (!CommonFunAni::ParseString(env, aniInFile, inFile)) {
227         APP_LOGE("parse aniInFile failed");
228         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_IN_FILE, TYPE_STRING);
229         return;
230     }
231 
232     std::string outFile;
233     if (!CommonFunAni::ParseString(env, aniOutFile, outFile)) {
234         APP_LOGE("parse aniOutFile failed");
235         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_OUT_FILE, TYPE_STRING);
236         return;
237     }
238 
239     LIBZIP::OPTIONS options;
240     if (!ANIParseOptions(env, aniOptions, options)) {
241         APP_LOGE("options parse failed.");
242         BusinessErrorAni::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_OPTIONS);
243         return;
244     }
245 
246     auto zlibCallbackInfo = std::make_shared<ANIZlibCallbackInfo>();
247     LIBZIP::Zip(inFile, outFile, options, false, zlibCallbackInfo);
248     const int32_t errCode = CommonFunc::ConvertErrCode(zlibCallbackInfo->GetResult());
249     if (errCode != ERR_OK) {
250         APP_LOGE("CompressFile failed, ret %{public}d", errCode);
251         BusinessErrorAni::ThrowCommonError(env, errCode, "", "");
252     }
253 }
254 
CompressFiles(ani_env * env,ani_object aniInFiles,ani_string aniOutFile,ani_object aniOptions)255 static void CompressFiles(ani_env* env, ani_object aniInFiles, ani_string aniOutFile, ani_object aniOptions)
256 {
257     RETURN_IF_NULL(env);
258     RETURN_IF_NULL(aniInFiles);
259     RETURN_IF_NULL(aniOutFile);
260     RETURN_IF_NULL(aniOptions);
261 
262     std::vector<std::string> inFiles;
263     if (aniInFiles == nullptr || !CommonFunAni::ParseStrArray(env, aniInFiles, inFiles)) {
264         APP_LOGE("inFiles parse failed.");
265         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_IN_FILES, TYPE_ARRAY);
266         return;
267     }
268 
269     std::string outFile;
270     if (!CommonFunAni::ParseString(env, aniOutFile, outFile)) {
271         APP_LOGE("parse aniOutFile failed");
272         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_OUT_FILE, TYPE_STRING);
273         return;
274     }
275 
276     LIBZIP::OPTIONS options;
277     if (!ANIParseOptions(env, aniOptions, options)) {
278         APP_LOGE("options parse failed.");
279         BusinessErrorAni::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_OPTIONS);
280         return;
281     }
282 
283     auto zlibCallbackInfo = std::make_shared<ANIZlibCallbackInfo>();
284     LIBZIP::Zips(inFiles, outFile, options, false, zlibCallbackInfo);
285     const int32_t errCode = CommonFunc::ConvertErrCode(zlibCallbackInfo->GetResult());
286     if (errCode != ERR_OK) {
287         APP_LOGE("CompressFiles failed, ret %{public}d", errCode);
288         BusinessErrorAni::ThrowCommonError(env, errCode, "", "");
289     }
290 }
291 
DecompressFile(ani_env * env,ani_string aniInFile,ani_string aniOutFile,ani_object aniOptions)292 static void DecompressFile(ani_env* env, ani_string aniInFile, ani_string aniOutFile, ani_object aniOptions)
293 {
294     RETURN_IF_NULL(env);
295     RETURN_IF_NULL(aniInFile);
296     RETURN_IF_NULL(aniOutFile);
297     RETURN_IF_NULL(aniOptions);
298 
299     std::string inFile;
300     if (!CommonFunAni::ParseString(env, aniInFile, inFile)) {
301         APP_LOGE("parse aniInFile failed");
302         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_IN_FILE, TYPE_STRING);
303         return;
304     }
305 
306     std::string outFile;
307     if (!CommonFunAni::ParseString(env, aniOutFile, outFile)) {
308         APP_LOGE("parse aniOutFile failed");
309         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_OUT_FILE, TYPE_STRING);
310         return;
311     }
312 
313     LIBZIP::OPTIONS options;
314     if (!ANIParseOptions(env, aniOptions, options)) {
315         APP_LOGE("options parse failed.");
316         BusinessErrorAni::ThrowError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_OPTIONS);
317         return;
318     }
319 
320     auto zlibCallbackInfo = std::make_shared<ANIZlibCallbackInfo>();
321     LIBZIP::Unzip(inFile, outFile, options, zlibCallbackInfo);
322     const int32_t errCode = CommonFunc::ConvertErrCode(zlibCallbackInfo->GetResult());
323     if (errCode != ERR_OK) {
324         APP_LOGE("DecompressFile failed, ret %{public}d", errCode);
325         BusinessErrorAni::ThrowCommonError(env, errCode, "", "");
326     }
327 }
328 
GetOriginalSize(ani_env * env,ani_string aniCompressedFile)329 static ani_double GetOriginalSize(ani_env* env, ani_string aniCompressedFile)
330 {
331     std::string compressedFile;
332     if (!CommonFunAni::ParseString(env, aniCompressedFile, compressedFile)) {
333         APP_LOGE("parse aniCompressedFile failed");
334         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_IN_FILE, TYPE_STRING);
335         return 0;
336     }
337 
338     int64_t originalSize = 0;
339     const int32_t errCode = CommonFunc::ConvertErrCode(LIBZIP::GetOriginalSize(compressedFile, originalSize));
340     if (errCode != ERR_OK) {
341         APP_LOGE("GetOriginalSize failed, ret %{public}d", errCode);
342         BusinessErrorAni::ThrowCommonError(env, errCode, "GetOriginalSize", "");
343     }
344 
345     return originalSize;
346 }
347 
CreateChecksumSync(ani_env * env)348 static ani_object CreateChecksumSync(ani_env* env)
349 {
350     Namespace zlibNS = Builder::BuildNamespace(NS_NAME_ZLIB);
351     Type checksumType = Builder::BuildClass({ zlibNS.Name(), TYPE_NAME_CHECKSUMINTERNAL });
352     ani_class clsChecksum = CommonFunAni::CreateClassByName(env, checksumType.Descriptor());
353     RETURN_NULL_IF_NULL(clsChecksum);
354     ani_object objChecksum = CommonFunAni::CreateNewObjectByClass(env, clsChecksum);
355     return objChecksum;
356 }
357 
Adler32(ani_env * env,ani_object checksumObj,ani_double aniAdler,ani_arraybuffer buf)358 static ani_double Adler32(
359     ani_env* env, [[maybe_unused]] ani_object checksumObj, ani_double aniAdler, ani_arraybuffer buf)
360 {
361     int64_t adler = 0;
362 
363     if (!CommonFunAni::TryCastDoubleTo(aniAdler, &adler)) {
364         APP_LOGE("Cast aniAdler failed");
365         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_ADLER, TYPE_NUMBER);
366         return 0;
367     }
368 
369     if (buf == nullptr) {
370         APP_LOGE("buf is nullptr");
371         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
372         return 0;
373     }
374 
375     size_t bufferLength = 0;
376     void* buffer = nullptr;
377     ani_status status = env->ArrayBuffer_GetInfo(buf, &buffer, &bufferLength);
378     if (status != ANI_OK) {
379         APP_LOGE("ArrayBuffer_GetInfo failed: %{public}d", status);
380         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
381         return 0;
382     }
383 
384     if (buffer == nullptr) {
385         APP_LOGE("native buf is nullptr");
386         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
387         return 0;
388     }
389 
390     return adler32(static_cast<uLong>(adler), reinterpret_cast<Bytef*>(buffer), static_cast<uInt>(bufferLength));
391 }
392 
Adler32Combine(ani_env * env,ani_object checksumObj,ani_double aniAdler1,ani_double aniAdler2,ani_double aniLen2)393 static ani_double Adler32Combine(ani_env* env,
394     [[maybe_unused]] ani_object checksumObj, ani_double aniAdler1, ani_double aniAdler2, ani_double aniLen2)
395 {
396     int64_t adler1 = 0;
397     int64_t adler2 = 0;
398     int64_t len2 = 0;
399 
400     if (!CommonFunAni::TryCastDoubleTo(aniAdler1, &adler1)) {
401         APP_LOGE("Cast aniAdler1 failed");
402         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_ADLER1, TYPE_NUMBER);
403         return 0;
404     }
405 
406     if (!CommonFunAni::TryCastDoubleTo(aniAdler2, &adler2)) {
407         APP_LOGE("Cast aniAdler2 failed");
408         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_ADLER2, TYPE_NUMBER);
409         return 0;
410     }
411 
412     if (!CommonFunAni::TryCastDoubleTo(aniLen2, &len2)) {
413         APP_LOGE("Cast aniLen2 failed");
414         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_LEN2, TYPE_NUMBER);
415         return 0;
416     }
417 
418 #ifdef Z_LARGE64
419     return adler32_combine64(static_cast<uLong>(adler1), static_cast<uLong>(adler2), static_cast<z_off64_t>(len2));
420 #else
421     return adler32_combine(static_cast<uLong>(adler1), static_cast<uLong>(adler2), static_cast<z_off64_t>(len2));
422 #endif
423 }
424 
Crc32(ani_env * env,ani_object checksumObj,ani_double aniCrc,ani_arraybuffer buf)425 static ani_double Crc32(ani_env* env, [[maybe_unused]] ani_object checksumObj, ani_double aniCrc, ani_arraybuffer buf)
426 {
427     int64_t crc = 0;
428 
429     if (!CommonFunAni::TryCastDoubleTo(aniCrc, &crc)) {
430         APP_LOGE("Cast aniCrc failed");
431         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_CRC, TYPE_NUMBER);
432         return 0;
433     }
434 
435     if (buf == nullptr) {
436         APP_LOGE("buf is nullptr");
437         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
438         return 0;
439     }
440 
441     size_t bufferLength = 0;
442     void* buffer = nullptr;
443     ani_status status = env->ArrayBuffer_GetInfo(buf, &buffer, &bufferLength);
444     if (status != ANI_OK) {
445         APP_LOGE("ArrayBuffer_GetInfo failed: %{public}d", status);
446         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
447         return 0;
448     }
449 
450     if (buffer == nullptr) {
451         APP_LOGE("native buf is nullptr");
452         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
453         return 0;
454     }
455 
456     return crc32(static_cast<uLong>(crc), reinterpret_cast<Bytef*>(buffer), static_cast<uInt>(bufferLength));
457 }
458 
Crc32Combine(ani_env * env,ani_object checksumObj,ani_double aniCrc1,ani_double aniCrc2,ani_double aniLen2)459 static ani_double Crc32Combine(ani_env* env,
460     [[maybe_unused]] ani_object checksumObj, ani_double aniCrc1, ani_double aniCrc2, ani_double aniLen2)
461 {
462     int64_t crc1 = 0;
463     int64_t crc2 = 0;
464     int64_t len2 = 0;
465 
466     if (!CommonFunAni::TryCastDoubleTo(aniCrc1, &crc1)) {
467         APP_LOGE("Cast aniCrc1 failed");
468         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_CRC1, TYPE_NUMBER);
469         return 0;
470     }
471 
472     if (!CommonFunAni::TryCastDoubleTo(aniCrc2, &crc2)) {
473         APP_LOGE("Cast aniCrc2 failed");
474         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_CRC2, TYPE_NUMBER);
475         return 0;
476     }
477 
478     if (!CommonFunAni::TryCastDoubleTo(aniLen2, &len2)) {
479         APP_LOGE("Cast aniLen2 failed");
480         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_LEN2, TYPE_NUMBER);
481         return 0;
482     }
483 
484 #ifdef Z_LARGE64
485     return crc32_combine64(static_cast<uLong>(crc1), static_cast<uLong>(crc2), static_cast<z_off64_t>(len2));
486 #else
487     return crc32_combine(static_cast<uLong>(crc1), static_cast<uLong>(crc2), static_cast<z_off64_t>(len2));
488 #endif
489 }
490 
Crc64(ani_env * env,ani_object checksumObj,ani_double aniCrc,ani_arraybuffer buf)491 static ani_double Crc64(ani_env* env, [[maybe_unused]] ani_object checksumObj, ani_double aniCrc, ani_arraybuffer buf)
492 {
493     uint64_t crc = 0;
494 
495     if (!CommonFunAni::TryCastDoubleTo(aniCrc, &crc)) {
496         APP_LOGE("Cast aniCrc failed");
497         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_CRC, TYPE_NUMBER);
498         return 0;
499     }
500 
501     if (buf == nullptr) {
502         APP_LOGE("buf is nullptr");
503         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
504         return 0;
505     }
506 
507     size_t bufferLength = 0;
508     void* buffer = nullptr;
509     ani_status status = env->ArrayBuffer_GetInfo(buf, &buffer, &bufferLength);
510     if (status != ANI_OK) {
511         APP_LOGE("ArrayBuffer_GetInfo failed: %{public}d", status);
512         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
513         return 0;
514     }
515 
516     if (buffer == nullptr) {
517         APP_LOGE("native buf is nullptr");
518         BusinessErrorAni::ThrowCommonError(env, ERROR_PARAM_CHECK_ERROR, PARAM_NAME_BUF, TYPE_ARRAYBUFFER);
519         return 0;
520     }
521 
522     return ComputeCrc64(crc, reinterpret_cast<char*>(buffer), bufferLength);
523 }
524 
GetCrcTable(ani_env * env,ani_object checksumObj)525 static ani_object GetCrcTable(ani_env* env, [[maybe_unused]] ani_object checksumObj)
526 {
527     return ConvertCRCTable(env, get_crc_table(), TABLE_SIZE);
528 }
529 
GetCrc64Table(ani_env * env,ani_object checksumObj)530 static ani_object GetCrc64Table(ani_env* env, [[maybe_unused]] ani_object checksumObj)
531 {
532     return ConvertCRCTable(env, CRC64_TABLE, TABLE_SIZE);
533 }
534 
BindNSMethods(ani_env * env)535 static ani_status BindNSMethods(ani_env* env)
536 {
537     Namespace zlibNS = Builder::BuildNamespace(NS_NAME_ZLIB);
538     ani_namespace kitNs = nullptr;
539     ani_status status = env->FindNamespace(zlibNS.Descriptor().c_str(), &kitNs);
540     if (status != ANI_OK) {
541         APP_LOGE("FindNamespace: %{public}s fail with %{public}d", NS_NAME_ZLIB, status);
542         return status;
543     }
544 
545     std::array methods = {
546         ani_native_function { "CompressFile", nullptr, reinterpret_cast<void*>(CompressFile) },
547         ani_native_function { "CompressFiles", nullptr, reinterpret_cast<void*>(CompressFiles) },
548         ani_native_function { "DecompressFile", nullptr, reinterpret_cast<void*>(DecompressFile) },
549         ani_native_function { "GetOriginalSize", nullptr, reinterpret_cast<void*>(GetOriginalSize) },
550         ani_native_function { "createChecksumSync", nullptr, reinterpret_cast<void*>(CreateChecksumSync) },
551     };
552 
553     status = env->Namespace_BindNativeFunctions(kitNs, methods.data(), methods.size());
554     if (status != ANI_OK) {
555         APP_LOGE("Namespace_BindNativeFunctions: %{public}s fail with %{public}d", NS_NAME_ZLIB, status);
556         return status;
557     }
558 
559     return status;
560 }
561 
BindChecksumMethods(ani_env * env)562 static ani_status BindChecksumMethods(ani_env* env)
563 {
564     Type checksumType = Builder::BuildClass({ NS_NAME_ZLIB, TYPE_NAME_CHECKSUMINTERNAL });
565     ani_class clsChecksum = CommonFunAni::CreateClassByName(env, checksumType.Descriptor());
566     if (clsChecksum == nullptr) {
567         APP_LOGE("CreateClassByName: %{public}s fail", TYPE_NAME_CHECKSUMINTERNAL);
568         return ANI_ERROR;
569     }
570 
571     std::array methodsChecksum = {
572         ani_native_function { "Adler32", nullptr, reinterpret_cast<void*>(Adler32) },
573         ani_native_function { "Adler32Combine", nullptr, reinterpret_cast<void*>(Adler32Combine) },
574         ani_native_function { "Crc32", nullptr, reinterpret_cast<void*>(Crc32) },
575         ani_native_function { "Crc32Combine", nullptr, reinterpret_cast<void*>(Crc32Combine) },
576         ani_native_function { "Crc64", nullptr, reinterpret_cast<void*>(Crc64) },
577         ani_native_function { "GetCrcTable", nullptr, reinterpret_cast<void*>(GetCrcTable) },
578         ani_native_function { "GetCrc64Table", nullptr, reinterpret_cast<void*>(GetCrc64Table) },
579     };
580 
581     ani_status status = env->Class_BindNativeMethods(clsChecksum, methodsChecksum.data(), methodsChecksum.size());
582     if (status != ANI_OK) {
583         APP_LOGE("Class_BindNativeMethods: %{public}s fail with %{public}d", TYPE_NAME_CHECKSUMINTERNAL, status);
584         return ANI_ERROR;
585     }
586 
587     return status;
588 }
589 
590 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)591 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
592 {
593     APP_LOGI("ANI_Constructor zlib called");
594     ani_env* env;
595     ani_status status = vm->GetEnv(ANI_VERSION_1, &env);
596     if (status != ANI_OK) {
597         APP_LOGE("Unsupported ANI_VERSION_1: %{public}d", status);
598         return status;
599     }
600 
601     status = BindNSMethods(env);
602     if (status != ANI_OK) {
603         APP_LOGE("BindNSMethods: %{public}d", status);
604         return status;
605     }
606 
607     status = BindChecksumMethods(env);
608     if (status != ANI_OK) {
609         APP_LOGE("BindChecksumMethods: %{public}d", status);
610         return status;
611     }
612 
613     *result = ANI_VERSION_1;
614 
615     APP_LOGI("ANI_Constructor finished");
616 
617     return ANI_OK;
618 }
619 }
620 } // namespace AppExecFwk
621 } // namespace OHOS