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