1 /*
2 * Copyright (c) 2021-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
16 #include "zip_file.h"
17
18 #include <ostream>
19
20 #include "app_log_wrapper.h"
21 #include "bundle_service_constants.h"
22 #include "securec.h"
23
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 constexpr uint32_t MAX_FILE_PATH = 4096;
28 constexpr uint32_t UNZIP_BUFFER_SIZE = 1024;
29 constexpr uint32_t UNZIP_BUF_IN_LEN = 160 * UNZIP_BUFFER_SIZE; // in buffer length: 160KB
30 constexpr uint32_t UNZIP_BUF_OUT_LEN = 320 * UNZIP_BUFFER_SIZE; // out buffer length: 320KB
31 constexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50;
32 constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50;
33 constexpr uint32_t EOCD_SIGNATURE = 0x06054b50;
34 constexpr uint32_t DATA_DESC_SIGNATURE = 0x08074b50;
35 constexpr uint32_t FLAG_DATA_DESC = 0x8;
36 constexpr size_t FILE_READ_COUNT = 1;
37 constexpr uint8_t INFLATE_ERROR_TIMES = 5;
38 } // namespace
39
ZipEntry(const CentralDirEntry & centralEntry)40 ZipEntry::ZipEntry(const CentralDirEntry ¢ralEntry)
41 {
42 compressionMethod = centralEntry.compressionMethod;
43 uncompressedSize = centralEntry.uncompressedSize;
44 compressedSize = centralEntry.compressedSize;
45 localHeaderOffset = centralEntry.localHeaderOffset;
46 crc = centralEntry.crc;
47 flags = centralEntry.flags;
48 }
49
ZipFile(const std::string & pathName)50 ZipFile::ZipFile(const std::string &pathName) : pathName_(pathName)
51 {
52 APP_LOGD("create instance from %{private}s", pathName_.c_str());
53 }
54
~ZipFile()55 ZipFile::~ZipFile()
56 {
57 Close();
58 }
59
SetContentLocation(const ZipPos start,const size_t length)60 void ZipFile::SetContentLocation(const ZipPos start, const size_t length)
61 {
62 APP_LOGD("set content location start position(%{public}llu), length(%{public}zu)", start, length);
63 fileStartPos_ = start;
64 fileLength_ = length;
65 }
66
CheckEndDir(const EndDir & endDir) const67 bool ZipFile::CheckEndDir(const EndDir &endDir) const
68 {
69 size_t lenEndDir = sizeof(EndDir);
70 if (endDir.numDisk != 0) {
71 APP_LOGE("endDir.numDisk != 0");
72 return false;
73 }
74 if (endDir.signature != EOCD_SIGNATURE) {
75 APP_LOGE("endDir.signature != EOCD_SIGNATURE");
76 return false;
77 }
78 if (endDir.startDiskOfCentralDir != 0) {
79 APP_LOGE("endDir.startDiskOfCentralDir != 0");
80 return false;
81 }
82 if (endDir.offset >= fileLength_) {
83 APP_LOGE("endDir.offset >= fileLength_");
84 return false;
85 }
86 if (endDir.totalEntriesInThisDisk != endDir.totalEntries) {
87 APP_LOGE("endDir.totalEntriesInThisDisk != endDir.totalEntries");
88 return false;
89 }
90 if (endDir.commentLen != 0) {
91 APP_LOGE("endDir.commentLen != 0");
92 return false;
93 }
94 if ((endDir.offset + endDir.sizeOfCentralDir + lenEndDir) > fileLength_) {
95 APP_LOGE("(endDir.offset + endDir.sizeOfCentralDir + lenEndDir) > fileLength_");
96 return false;
97 }
98 return true;
99 }
100
ParseEndDirectory()101 bool ZipFile::ParseEndDirectory()
102 {
103 size_t endDirLen = sizeof(EndDir);
104 size_t endFilePos = fileStartPos_ + fileLength_;
105
106 if (fileLength_ <= endDirLen) {
107 APP_LOGE("parse EOCD file length(%{public}llu) <= end dir length(%{public}llu)", fileStartPos_, fileLength_);
108 return false;
109 }
110
111 size_t eocdPos = endFilePos - endDirLen;
112 if (fseek(file_, eocdPos, SEEK_SET) != 0) {
113 APP_LOGE("locate EOCD seek failed, error: %{public}d", errno);
114 return false;
115 }
116
117 if (fread(&endDir_, sizeof(EndDir), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
118 APP_LOGE("read EOCD struct failed, error: %{public}d", errno);
119 return false;
120 }
121
122 centralDirPos_ = endDir_.offset + fileStartPos_;
123 APP_LOGD("parse EOCD offset(0x%{public}08x) file start position(0x%{public}08llx)", endDir_.offset, fileStartPos_);
124
125 return CheckEndDir(endDir_);
126 }
127
ParseAllEntries()128 bool ZipFile::ParseAllEntries()
129 {
130 bool ret = true;
131 ZipPos currentPos = centralDirPos_;
132 CentralDirEntry directoryEntry = {0};
133
134 for (uint16_t i = 0; i < endDir_.totalEntries; i++) {
135 std::string fileName;
136 fileName.reserve(MAX_FILE_PATH);
137 fileName.resize(MAX_FILE_PATH - 1);
138
139 if (fseek(file_, currentPos, SEEK_SET) != 0) {
140 APP_LOGE("parse entry(%{public}d) seek zipEntry failed, error: %{public}d", i, errno);
141 ret = false;
142 break;
143 }
144
145 if (fread(&directoryEntry, sizeof(CentralDirEntry), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
146 APP_LOGE("parse entry(%{public}d) read ZipEntry failed, error: %{public}d", i, errno);
147 ret = false;
148 break;
149 }
150
151 if (directoryEntry.signature != CENTRAL_SIGNATURE) {
152 APP_LOGE("parse entry(%{public}d) check signature(0x%08x) at pos(0x%08llx) failed",
153 i,
154 directoryEntry.signature,
155 currentPos);
156 ret = false;
157 break;
158 }
159
160 size_t fileLength = (directoryEntry.nameSize >= MAX_FILE_PATH) ? (MAX_FILE_PATH - 1) : directoryEntry.nameSize;
161 if (fread(&(fileName[0]), fileLength, FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
162 APP_LOGE("parse entry(%{public}d) read file name failed, error: %{public}d", i, errno);
163 ret = false;
164 break;
165 }
166 fileName.resize(fileLength);
167
168 ZipEntry currentEntry(directoryEntry);
169 currentEntry.fileName = fileName;
170 entriesMap_[fileName] = currentEntry;
171
172 currentPos += sizeof(directoryEntry);
173 currentPos += directoryEntry.nameSize + directoryEntry.extraSize + directoryEntry.commentSize;
174 }
175
176 APP_LOGD("parse %{public}d central entries from %{private}s", endDir_.totalEntries, pathName_.c_str());
177 return ret;
178 }
179
Open()180 bool ZipFile::Open()
181 {
182 APP_LOGD("open: %{private}s", pathName_.c_str());
183
184 if (isOpen_) {
185 APP_LOGE("has already opened");
186 return true;
187 }
188
189 if (pathName_.length() > PATH_MAX) {
190 APP_LOGE("path length(%{public}u) longer than max length(%{public}d)",
191 static_cast<unsigned int>(pathName_.length()),
192 PATH_MAX);
193 return false;
194 }
195 std::string realPath;
196 realPath.reserve(PATH_MAX);
197 realPath.resize(PATH_MAX - 1);
198 if (realpath(pathName_.c_str(), &(realPath[0])) == nullptr) {
199 APP_LOGE("transform real path: %{private}s error: %{public}d", pathName_.c_str(), errno);
200 return false;
201 }
202
203 FILE *tmpFile = fopen(realPath.c_str(), "rb");
204 if (tmpFile == nullptr) {
205 APP_LOGE("open file(%{private}s) failed, error: %{public}d", pathName_.c_str(), errno);
206 return false;
207 }
208
209 if (fileLength_ == 0) {
210 if (fseek(tmpFile, 0, SEEK_END) != 0) {
211 APP_LOGE("file seek failed, error: %{public}d", errno);
212 fclose(tmpFile);
213 return false;
214 }
215 int64_t fileLength = ftell(tmpFile);
216 if (fileLength == -1) {
217 APP_LOGE("open file %{private}s failed", pathName_.c_str());
218 fclose(tmpFile);
219 return false;
220 }
221 fileLength_ = static_cast<ZipPos>(fileLength);
222 if (fileStartPos_ >= fileLength_) {
223 APP_LOGE("open start pos > length failed");
224 fclose(tmpFile);
225 return false;
226 }
227
228 fileLength_ -= fileStartPos_;
229 }
230
231 file_ = tmpFile;
232 bool result = ParseEndDirectory();
233 if (result) {
234 result = ParseAllEntries();
235 }
236 // it means open file success.
237 isOpen_ = true;
238 return result;
239 }
240
Close()241 void ZipFile::Close()
242 {
243 APP_LOGD("close: %{private}s", pathName_.c_str());
244
245 if (!isOpen_ || file_ == nullptr) {
246 APP_LOGW("file is not opened");
247 return;
248 }
249
250 entriesMap_.clear();
251 pathName_ = "";
252 isOpen_ = false;
253
254 if (fclose(file_) != 0) {
255 APP_LOGW("close failed err: %{public}d", errno);
256 }
257 file_ = nullptr;
258 }
259
260 // Get all file zipEntry in this file
GetAllEntries() const261 const ZipEntryMap &ZipFile::GetAllEntries() const
262 {
263 return entriesMap_;
264 }
265
HasEntry(const std::string & entryName) const266 bool ZipFile::HasEntry(const std::string &entryName) const
267 {
268 return entriesMap_.find(entryName) != entriesMap_.end();
269 }
270
IsDirExist(const std::string & dir) const271 bool ZipFile::IsDirExist(const std::string &dir) const
272 {
273 APP_LOGD("target dir: %{public}s", dir.c_str());
274 if (dir.empty()) {
275 APP_LOGE("target dir is empty");
276 return false;
277 }
278
279 auto tempDir = dir;
280 if (tempDir.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
281 tempDir.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
282 }
283
284 for (const auto &item : entriesMap_) {
285 if (item.first.find(tempDir) == 0) {
286 APP_LOGD("find target dir, fileName : %{public}s", item.first.c_str());
287 return true;
288 }
289 }
290 APP_LOGD("target dir not found, dir : %{public}s", dir.c_str());
291 return false;
292 }
293
GetEntry(const std::string & entryName,ZipEntry & resultEntry) const294 bool ZipFile::GetEntry(const std::string &entryName, ZipEntry &resultEntry) const
295 {
296 APP_LOGD("get entry by name: %{public}s", entryName.c_str());
297 auto iter = entriesMap_.find(entryName);
298 if (iter != entriesMap_.end()) {
299 resultEntry = iter->second;
300 APP_LOGD("get entry succeed");
301 return true;
302 }
303 APP_LOGE("get entry failed");
304 return false;
305 }
306
GetLocalHeaderSize(const uint16_t nameSize,const uint16_t extraSize) const307 size_t ZipFile::GetLocalHeaderSize(const uint16_t nameSize, const uint16_t extraSize) const
308 {
309 return sizeof(LocalHeader) + nameSize + extraSize;
310 }
311
CheckDataDesc(const ZipEntry & zipEntry,const LocalHeader & localHeader) const312 bool ZipFile::CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const
313 {
314 uint32_t crcLocal = 0;
315 uint32_t compressedLocal = 0;
316 uint32_t uncompressedLocal = 0;
317
318 if (localHeader.flags & FLAG_DATA_DESC) { // use data desc
319 DataDesc dataDesc;
320 auto descPos = zipEntry.localHeaderOffset + GetLocalHeaderSize(localHeader.nameSize, localHeader.extraSize);
321 descPos += fileStartPos_ + zipEntry.compressedSize;
322
323 if (fseek(file_, descPos, SEEK_SET) != 0) {
324 APP_LOGE("check local header seek datadesc failed, error: %{public}d", errno);
325 return false;
326 }
327
328 if (fread(&dataDesc, sizeof(DataDesc), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
329 APP_LOGE("check local header read datadesc failed, error: %{public}d", errno);
330 return false;
331 }
332
333 if (dataDesc.signature != DATA_DESC_SIGNATURE) {
334 APP_LOGE("check local header check datadesc signature failed");
335 return false;
336 }
337
338 crcLocal = dataDesc.crc;
339 compressedLocal = dataDesc.compressedSize;
340 uncompressedLocal = dataDesc.uncompressedSize;
341 } else {
342 crcLocal = localHeader.crc;
343 compressedLocal = localHeader.compressedSize;
344 uncompressedLocal = localHeader.uncompressedSize;
345 }
346
347 if ((zipEntry.crc != crcLocal) || (zipEntry.compressedSize != compressedLocal) ||
348 (zipEntry.uncompressedSize != uncompressedLocal)) {
349 APP_LOGE("check local header compressed size corrupted");
350 return false;
351 }
352
353 return true;
354 }
355
CheckCoherencyLocalHeader(const ZipEntry & zipEntry,uint16_t & extraSize) const356 bool ZipFile::CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const
357 {
358 LocalHeader localHeader = {0};
359
360 if (zipEntry.localHeaderOffset >= fileLength_) {
361 APP_LOGE("check local file header offset overflow %{public}d", zipEntry.localHeaderOffset);
362 return false;
363 }
364
365 if (fseek(file_, fileStartPos_ + zipEntry.localHeaderOffset, SEEK_SET) != 0) {
366 APP_LOGE("check local header seek failed, error: %{public}d", errno);
367 return false;
368 }
369
370 if (fread(&localHeader, sizeof(LocalHeader), FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
371 APP_LOGE("check local header read localheader failed, error: %{public}d", errno);
372 return false;
373 }
374
375 if ((localHeader.signature != LOCAL_HEADER_SIGNATURE) ||
376 (zipEntry.compressionMethod != localHeader.compressionMethod)) {
377 APP_LOGE("check local header signature or compressionMethod failed");
378 return false;
379 }
380
381 // current only support store and Z_DEFLATED method
382 if ((zipEntry.compressionMethod != Z_DEFLATED) && (zipEntry.compressionMethod != 0)) {
383 APP_LOGE("check local header compressionMethod(%{public}d) not support", zipEntry.compressionMethod);
384 return false;
385 }
386
387 std::string fileName;
388 fileName.reserve(MAX_FILE_PATH);
389 fileName.resize(MAX_FILE_PATH - 1);
390 size_t fileLength = (localHeader.nameSize >= MAX_FILE_PATH) ? (MAX_FILE_PATH - 1) : localHeader.nameSize;
391 if (fileLength != zipEntry.fileName.length()) {
392 APP_LOGE("check local header file name size failed");
393 return false;
394 }
395 if (fread(&(fileName[0]), fileLength, FILE_READ_COUNT, file_) != FILE_READ_COUNT) {
396 APP_LOGE("check local header read file name failed, error: %{public}d", errno);
397 return false;
398 }
399 fileName.resize(fileLength);
400 if (zipEntry.fileName != fileName) {
401 APP_LOGE("check local header file name corrupted");
402 return false;
403 }
404
405 if (!CheckDataDesc(zipEntry, localHeader)) {
406 APP_LOGE("check data desc failed");
407 return false;
408 }
409
410 extraSize = localHeader.extraSize;
411 return true;
412 }
413
SeekToEntryStart(const ZipEntry & zipEntry,const uint16_t extraSize) const414 bool ZipFile::SeekToEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const
415 {
416 ZipPos startOffset = zipEntry.localHeaderOffset;
417 // get data offset, add signature+localheader+namesize+extrasize
418 startOffset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize);
419 if (startOffset + zipEntry.compressedSize > fileLength_) {
420 APP_LOGE("startOffset(%{public}lld)+entryCompressedSize(%{public}ud) > fileLength(%{public}llu)",
421 startOffset,
422 zipEntry.compressedSize,
423 fileLength_);
424 return false;
425 }
426 startOffset += fileStartPos_; // add file start relative to file stream
427
428 APP_LOGD("seek to entry start 0x%{public}08llx", startOffset);
429 if (fseek(file_, startOffset, SEEK_SET) != 0) {
430 APP_LOGE("seek failed, error: %{public}d", errno);
431 return false;
432 }
433 return true;
434 }
435
UnzipWithStore(const ZipEntry & zipEntry,const uint16_t extraSize,std::ostream & dest) const436 bool ZipFile::UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const
437 {
438 APP_LOGD("unzip with store");
439
440 if (!SeekToEntryStart(zipEntry, extraSize)) {
441 APP_LOGE("seek to entry start failed");
442 return false;
443 }
444
445 uint32_t remainSize = zipEntry.compressedSize;
446 std::string readBuffer;
447 readBuffer.reserve(UNZIP_BUF_OUT_LEN);
448 readBuffer.resize(UNZIP_BUF_OUT_LEN - 1);
449 while (remainSize > 0) {
450 size_t readBytes;
451 size_t readLen = (remainSize > UNZIP_BUF_OUT_LEN) ? UNZIP_BUF_OUT_LEN : remainSize;
452 readBytes = fread(&(readBuffer[0]), sizeof(Byte), readLen, file_);
453 if (readBytes == 0) {
454 APP_LOGE("unzip store read failed, error: %{public}d", ferror(file_));
455 return false;
456 }
457 remainSize -= readBytes;
458 dest.write(&(readBuffer[0]), readBytes);
459 }
460
461 return true;
462 }
463
InitZStream(z_stream & zstream) const464 bool ZipFile::InitZStream(z_stream &zstream) const
465 {
466 // init zlib stream
467 if (memset_s(&zstream, sizeof(z_stream), 0, sizeof(z_stream))) {
468 APP_LOGE("unzip stream buffer init failed");
469 return false;
470 }
471 int32_t zlibErr = inflateInit2(&zstream, -MAX_WBITS);
472 if (zlibErr != Z_OK) {
473 APP_LOGE("unzip inflated init failed");
474 return false;
475 }
476
477 BytePtr bufOut = new (std::nothrow) Byte[UNZIP_BUF_OUT_LEN];
478 if (bufOut == nullptr) {
479 APP_LOGE("unzip inflated new out buffer failed");
480 return false;
481 }
482
483 BytePtr bufIn = new (std::nothrow) Byte[UNZIP_BUF_IN_LEN];
484 if (bufIn == nullptr) {
485 APP_LOGE("unzip inflated new in buffer failed");
486 delete[] bufOut;
487 return false;
488 }
489 zstream.next_out = bufOut;
490 zstream.next_in = bufIn;
491 zstream.avail_out = UNZIP_BUF_OUT_LEN;
492 return true;
493 }
494
ReadZStream(const BytePtr & buffer,z_stream & zstream,uint32_t & remainCompressedSize) const495 bool ZipFile::ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize) const
496 {
497 if (zstream.avail_in == 0) {
498 size_t readBytes;
499 size_t remainBytes = (remainCompressedSize > UNZIP_BUF_IN_LEN) ? UNZIP_BUF_IN_LEN : remainCompressedSize;
500 readBytes = fread(buffer, sizeof(Byte), remainBytes, file_);
501 if (readBytes == 0) {
502 APP_LOGE("unzip inflated read failed, error: %{public}d", ferror(file_));
503 return false;
504 }
505
506 remainCompressedSize -= readBytes;
507 zstream.avail_in = readBytes;
508 zstream.next_in = buffer;
509 }
510 return true;
511 }
512
UnzipWithInflated(const ZipEntry & zipEntry,const uint16_t extraSize,std::ostream & dest) const513 bool ZipFile::UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const
514 {
515 APP_LOGD("unzip with inflated");
516
517 z_stream zstream;
518 if (!SeekToEntryStart(zipEntry, extraSize) || !InitZStream(zstream)) {
519 return false;
520 }
521
522 BytePtr bufIn = zstream.next_in;
523 BytePtr bufOut = zstream.next_out;
524
525 bool ret = true;
526 int32_t zlibErr = Z_OK;
527 uint32_t remainCompressedSize = zipEntry.compressedSize;
528 uint8_t errorTimes = 0;
529 while ((remainCompressedSize > 0) || (zstream.avail_in > 0)) {
530 if (!ReadZStream(bufIn, zstream, remainCompressedSize)) {
531 ret = false;
532 break;
533 }
534
535 zlibErr = inflate(&zstream, Z_SYNC_FLUSH);
536 if ((zlibErr >= Z_OK) && (zstream.msg != nullptr)) {
537 APP_LOGE("unzip inflated inflate, error: %{public}d, err msg: %{public}s", zlibErr, zstream.msg);
538 ret = false;
539 break;
540 }
541
542 size_t inflateLen = UNZIP_BUF_OUT_LEN - zstream.avail_out;
543 if (inflateLen > 0) {
544 dest.write(reinterpret_cast<const char *>(bufOut), inflateLen);
545 zstream.next_out = bufOut;
546 zstream.avail_out = UNZIP_BUF_OUT_LEN;
547 errorTimes = 0;
548 } else {
549 errorTimes++;
550 }
551 if (errorTimes >= INFLATE_ERROR_TIMES) {
552 APP_LOGE("unzip inflated data is abnormal");
553 ret = false;
554 break;
555 }
556 }
557
558 // free all dynamically allocated data structures except the next_in and next_out for this stream.
559 zlibErr = inflateEnd(&zstream);
560 if (zlibErr != Z_OK) {
561 APP_LOGE("unzip inflateEnd error %{public}d", zlibErr);
562 ret = false;
563 }
564
565 delete[] bufOut;
566 delete[] bufIn;
567 return ret;
568 }
569
GetEntryDataOffset(const ZipEntry & zipEntry,const uint16_t extraSize) const570 ZipPos ZipFile::GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const
571 {
572 // get entry data offset relative file
573 ZipPos offset = zipEntry.localHeaderOffset;
574
575 offset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize);
576 offset += fileStartPos_;
577
578 return offset;
579 }
580
GetDataOffsetRelative(const std::string & file,ZipPos & offset,uint32_t & length) const581 bool ZipFile::GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const
582 {
583 APP_LOGD("get data relative offset for file %{private}s", file.c_str());
584
585 ZipEntry zipEntry;
586 if (!GetEntry(file, zipEntry)) {
587 APP_LOGE("extract file: not find file");
588 return false;
589 }
590
591 uint16_t extraSize = 0;
592 if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
593 APP_LOGE("check coherency local header failed");
594 return false;
595 }
596
597 offset = GetEntryDataOffset(zipEntry, extraSize);
598 length = zipEntry.compressedSize;
599 return true;
600 }
601
ExtractFile(const std::string & file,std::ostream & dest) const602 bool ZipFile::ExtractFile(const std::string &file, std::ostream &dest) const
603 {
604 APP_LOGD("extract file %{private}s", file.c_str());
605
606 ZipEntry zipEntry;
607 if (!GetEntry(file, zipEntry)) {
608 APP_LOGE("extract file: not find file");
609 return false;
610 }
611
612 uint16_t extraSize = 0;
613 if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
614 APP_LOGE("check coherency local header failed");
615 return false;
616 }
617
618 bool ret = true;
619 if (zipEntry.compressionMethod == 0) {
620 ret = UnzipWithStore(zipEntry, extraSize, dest);
621 } else {
622 ret = UnzipWithInflated(zipEntry, extraSize, dest);
623 }
624
625 return ret;
626 }
627 } // namespace AppExecFwk
628 } // namespace OHOS
629