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 "zip.h"
16 
17 #include <fcntl.h>
18 #include <list>
19 #include <stdio.h>
20 #include <string>
21 #include <unistd.h>
22 #include <vector>
23 
24 #include "app_log_wrapper.h"
25 #include "appexecfwk_errors.h"
26 #include "bundle_errors.h"
27 #include "directory_ex.h"
28 #include "event_handler.h"
29 #include "file_path.h"
30 #include "zip_internal.h"
31 #include "zip_reader.h"
32 #include "zip_writer.h"
33 
34 using namespace OHOS::AppExecFwk;
35 
36 namespace OHOS {
37 namespace AppExecFwk {
38 namespace LIBZIP {
39 namespace {
40 using FilterCallback = std::function<bool(const FilePath &)>;
41 using DirectoryCreator = std::function<bool(FilePath &, FilePath &)>;
42 using WriterFactory = std::function<std::unique_ptr<WriterDelegate>(FilePath &, FilePath &)>;
43 
44 const std::string SEPARATOR = "/";
45 const char HIDDEN_SEPARATOR = '.';
46 const std::string ZIP = ".zip";
47 
48 struct UnzipParam {
49     FilterCallback filterCB = nullptr;
50     bool logSkippedFiles = false;
51 };
IsHiddenFile(const FilePath & filePath)52 bool IsHiddenFile(const FilePath &filePath)
53 {
54     FilePath localFilePath = filePath;
55     if (!localFilePath.Value().empty()) {
56         return localFilePath.Value()[0] == HIDDEN_SEPARATOR;
57     } else {
58         return false;
59     }
60 }
ExcludeNoFilesFilter(const FilePath & filePath)61 bool ExcludeNoFilesFilter(const FilePath &filePath)
62 {
63     return true;
64 }
65 
ExcludeHiddenFilesFilter(const FilePath & filePath)66 bool ExcludeHiddenFilesFilter(const FilePath &filePath)
67 {
68     return !IsHiddenFile(filePath);
69 }
70 
ListDirectoryContent(const FilePath & filePath,bool & isSuccess)71 std::vector<FileAccessor::DirectoryContentEntry> ListDirectoryContent(const FilePath &filePath, bool& isSuccess)
72 {
73     FilePath curPath = filePath;
74     std::vector<FileAccessor::DirectoryContentEntry> fileDirectoryVector;
75     std::vector<std::string> filelist;
76     isSuccess = FilePath::GetZipAllDirFiles(curPath.Value(), filelist);
77     if (isSuccess) {
78         APP_LOGD("f.size=%{public}zu", filelist.size());
79         for (size_t i = 0; i < filelist.size(); i++) {
80             std::string str(filelist[i]);
81             if (!str.empty()) {
82                 fileDirectoryVector.push_back(
83                     FileAccessor::DirectoryContentEntry(FilePath(str), FilePath::DirectoryExists(FilePath(str))));
84             }
85         }
86     }
87     return fileDirectoryVector;
88 }
89 
90 // Creates a directory at |extractDir|/|entryPath|, including any parents.
CreateDirectory(FilePath & extractDir,FilePath & entryPath)91 bool CreateDirectory(FilePath &extractDir, FilePath &entryPath)
92 {
93     std::string path = extractDir.Value();
94     if (EndsWith(path, SEPARATOR)) {
95         return FilePath::CreateDirectory(FilePath(extractDir.Value() + entryPath.Value()));
96     } else {
97         return FilePath::CreateDirectory(FilePath(extractDir.Value() + "/" + entryPath.Value()));
98     }
99 }
100 
101 // Creates a WriterDelegate that can write a file at |extractDir|/|entryPath|.
CreateFilePathWriterDelegate(FilePath & extractDir,FilePath entryPath)102 std::unique_ptr<WriterDelegate> CreateFilePathWriterDelegate(FilePath &extractDir, FilePath entryPath)
103 {
104     if (EndsWith(extractDir.Value(), SEPARATOR)) {
105         return std::make_unique<FilePathWriterDelegate>(FilePath(extractDir.Value() + entryPath.Value()));
106     } else {
107         return std::make_unique<FilePathWriterDelegate>(FilePath(extractDir.Value() + "/" + entryPath.Value()));
108     }
109 }
110 }  // namespace
111 
ZipParams(const std::vector<FilePath> & srcDir,const FilePath & destFile)112 ZipParams::ZipParams(const std::vector<FilePath>& srcDir, const FilePath& destFile)
113     : srcDir_(srcDir), destFile_(destFile)
114 {}
115 
116 // Does not take ownership of |fd|.
ZipParams(const std::vector<FilePath> & srcDir,int destFd)117 ZipParams::ZipParams(const std::vector<FilePath> &srcDir, int destFd) : srcDir_(srcDir), destFd_(destFd)
118 {}
119 
FilePathEndIsSeparator(FilePath paramPath)120 FilePath FilePathEndIsSeparator(FilePath paramPath)
121 {
122     bool endIsSeparator = EndsWith(paramPath.Value(), SEPARATOR);
123     if (FilePath::IsDir(paramPath)) {
124         if (!endIsSeparator) {
125             paramPath.AppendSeparator();
126         }
127     }
128     return paramPath;
129 }
130 
Zip(const ZipParams & params,const OPTIONS & options)131 bool Zip(const ZipParams &params, const OPTIONS &options)
132 {
133     const std::vector<std::pair<FilePath, FilePath>> *filesToAdd = &params.GetFilesTozip();
134     std::vector<std::pair<FilePath, FilePath>> allRelativeFiles;
135     FilePath srcDir = params.SrcDir().front();
136     FilePath paramPath = FilePathEndIsSeparator(srcDir);
137     if (filesToAdd->empty()) {
138         filesToAdd = &allRelativeFiles;
139         std::list<FileAccessor::DirectoryContentEntry> entries;
140         if (EndsWith(paramPath.Value(), SEPARATOR)) {
141             entries.push_back(FileAccessor::DirectoryContentEntry(srcDir, true));
142             FilterCallback filterCallback = params.GetFilterCallback();
143             for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
144                 if (iter != entries.begin() && ((!params.GetIncludeHiddenFiles() && IsHiddenFile(iter->path)) ||
145                     (filterCallback && !filterCallback(iter->path)))) {
146                     continue;
147                 }
148                 if (iter != entries.begin()) {
149                     FilePath relativePath;
150                     FilePath paramsSrcPath = srcDir;
151                     if (paramsSrcPath.AppendRelativePath(iter->path, &relativePath)) {
152                         allRelativeFiles.push_back(std::make_pair(relativePath, iter->path));
153                     }
154                 }
155                 if (iter->isDirectory) {
156                     bool isSuccess = false;
157                     std::vector<FileAccessor::DirectoryContentEntry> subEntries =
158                         ListDirectoryContent(iter->path, isSuccess);
159                     entries.insert(entries.end(), subEntries.begin(), subEntries.end());
160                 }
161             }
162         } else {
163             allRelativeFiles.push_back(std::make_pair(paramPath.BaseName(), paramPath));
164         }
165     }
166     std::unique_ptr<ZipWriter> zipWriter = nullptr;
167     if (params.DestFd() != kInvalidPlatformFile) {
168         zipWriter = std::make_unique<ZipWriter>(ZipWriter::InitZipFileWithFd(params.DestFd()));
169     } else {
170         zipWriter = std::make_unique<ZipWriter>(ZipWriter::InitZipFileWithFile(params.DestFile()));
171     }
172     if (zipWriter == nullptr) {
173         APP_LOGE("Init zipWriter failed");
174         return false;
175     }
176     return zipWriter->WriteEntries(*filesToAdd, options);
177 }
178 
GetZipsAllRelativeFilesInner(const ZipParams & params,const FilePath & iterPath,std::list<FileAccessor::DirectoryContentEntry> & entries,std::vector<std::pair<FilePath,FilePath>> & allRelativeFiles)179 void GetZipsAllRelativeFilesInner(const ZipParams &params, const FilePath &iterPath,
180     std::list<FileAccessor::DirectoryContentEntry> &entries,
181     std::vector<std::pair<FilePath, FilePath>> &allRelativeFiles)
182 {
183     FilterCallback filterCallback = params.GetFilterCallback();
184     for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
185         if (iter != entries.begin() && ((!params.GetIncludeHiddenFiles() && IsHiddenFile(iter->path)) ||
186             (filterCallback && !filterCallback(iter->path)))) {
187             continue;
188         }
189         if (iter != entries.begin()) {
190             FilePath relativePath;
191             FilePath paramsSrcPath = iterPath;
192             if (paramsSrcPath.AppendRelativePath(iter->path, &relativePath)) {
193                 allRelativeFiles.push_back(std::make_pair(relativePath, iter->path));
194             }
195         }
196         if (iter->isDirectory) {
197             bool isSuccess = false;
198             std::vector<FileAccessor::DirectoryContentEntry> subEntries = ListDirectoryContent(iter->path, isSuccess);
199             entries.insert(entries.end(), subEntries.begin(), subEntries.end());
200         }
201     }
202 }
203 
GetZipsAllRelativeFiles(const ZipParams & params,std::vector<std::pair<FilePath,FilePath>> & allRelativeFiles,std::vector<FilePath> & srcFiles)204 void GetZipsAllRelativeFiles(const ZipParams &params, std::vector<std::pair<FilePath, FilePath>> &allRelativeFiles,
205     std::vector<FilePath> &srcFiles)
206 {
207     std::list<FileAccessor::DirectoryContentEntry> entries;
208     for (auto iterPath = srcFiles.begin(); iterPath != srcFiles.end(); ++iterPath) {
209         FilePath paramPath = FilePathEndIsSeparator(*iterPath);
210         if (!EndsWith(paramPath.Value(), SEPARATOR)) {
211             allRelativeFiles.push_back(std::make_pair(paramPath.BaseName(), paramPath));
212             continue;
213         }
214         entries.clear();
215         entries.push_back(FileAccessor::DirectoryContentEntry(*iterPath, true));
216         GetZipsAllRelativeFilesInner(params, *iterPath, entries, allRelativeFiles);
217     }
218 }
219 
Zips(const ZipParams & params,const OPTIONS & options)220 bool Zips(const ZipParams &params, const OPTIONS &options)
221 {
222     const std::vector<std::pair<FilePath, FilePath>> *filesToAdd = &params.GetFilesTozip();
223     std::vector<std::pair<FilePath, FilePath>> allRelativeFiles;
224     std::vector<FilePath> srcFiles = params.SrcDir();
225     if (filesToAdd->empty()) {
226         filesToAdd = &allRelativeFiles;
227         GetZipsAllRelativeFiles(params, allRelativeFiles, srcFiles);
228     }
229     std::unique_ptr<ZipWriter> zipWriter = nullptr;
230     if (params.DestFd() != kInvalidPlatformFile) {
231         zipWriter = std::make_unique<ZipWriter>(ZipWriter::InitZipFileWithFd(params.DestFd()));
232     } else {
233         zipWriter = std::make_unique<ZipWriter>(ZipWriter::InitZipFileWithFile(params.DestFile()));
234     }
235     if (zipWriter == nullptr) {
236         APP_LOGE("Init zipWriter failed");
237         return false;
238     }
239     return zipWriter->WriteEntries(*filesToAdd, options);
240 }
241 
UnzipWithFilterAndWriters(const PlatformFile & srcFile,FilePath & destDir,WriterFactory writerFactory,DirectoryCreator directoryCreator,UnzipParam & unzipParam)242 ErrCode UnzipWithFilterAndWriters(const PlatformFile &srcFile, FilePath &destDir, WriterFactory writerFactory,
243     DirectoryCreator directoryCreator, UnzipParam &unzipParam)
244 {
245     APP_LOGD("destDir=%{private}s", destDir.Value().c_str());
246     ZipReader reader;
247     if (!reader.OpenFromPlatformFile(srcFile)) {
248         APP_LOGI("Failed to open srcFile");
249         return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
250     }
251     while (reader.HasMore()) {
252         if (!reader.OpenCurrentEntryInZip()) {
253             APP_LOGI("Failed to open the current file in zip");
254             return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
255         }
256         const FilePath &constEntryPath = reader.CurrentEntryInfo()->GetFilePath();
257         FilePath entryPath = constEntryPath;
258         if (reader.CurrentEntryInfo()->IsUnsafe()) {
259             APP_LOGI("Found an unsafe file in zip");
260             return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
261         }
262         // callback
263         if (unzipParam.filterCB(entryPath)) {
264             if (reader.CurrentEntryInfo()->IsDirectory()) {
265                 if (!directoryCreator(destDir, entryPath)) {
266                     APP_LOGI("directory_creator(%{private}s) Failed", entryPath.Value().c_str());
267                     return ERR_ZLIB_DEST_FILE_DISABLED;
268                 }
269             } else {
270                 std::unique_ptr<WriterDelegate> writer = writerFactory(destDir, entryPath);
271                 if (!reader.ExtractCurrentEntry(writer.get(), std::numeric_limits<uint64_t>::max())) {
272                     APP_LOGI("Failed to extract");
273                     return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
274                 }
275             }
276         } else if (unzipParam.logSkippedFiles) {
277             APP_LOGI("Skipped file");
278         }
279 
280         if (!reader.AdvanceToNextEntry()) {
281             APP_LOGI("Failed to advance to the next file");
282             return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
283         }
284     }
285     return ERR_OK;
286 }
287 
UnzipWithFilterCallback(const FilePath & srcFile,const FilePath & destDir,const OPTIONS & options,UnzipParam & unzipParam)288 ErrCode UnzipWithFilterCallback(
289     const FilePath &srcFile, const FilePath &destDir, const OPTIONS &options, UnzipParam &unzipParam)
290 {
291     FilePath src = srcFile;
292     if (!FilePathCheckValid(src.Value())) {
293         APP_LOGI("FilePathCheckValid returnValue is false");
294         return ERR_ZLIB_SRC_FILE_DISABLED;
295     }
296 
297     FilePath dest = destDir;
298 
299     APP_LOGD("srcFile=%{private}s, destFile=%{private}s", src.Value().c_str(), dest.Value().c_str());
300 
301     if (!FilePath::PathIsValid(srcFile)) {
302         APP_LOGI("PathIsValid return value is false");
303         return ERR_ZLIB_SRC_FILE_DISABLED;
304     }
305 
306     PlatformFile zipFd = open(src.Value().c_str(), S_IREAD, O_CREAT);
307     if (zipFd == kInvalidPlatformFile) {
308         APP_LOGI("Failed to open");
309         return ERR_ZLIB_SRC_FILE_DISABLED;
310     }
311     ErrCode ret = UnzipWithFilterAndWriters(zipFd,
312         dest,
313         std::bind(&CreateFilePathWriterDelegate, std::placeholders::_1, std::placeholders::_2),
314         std::bind(&CreateDirectory, std::placeholders::_1, std::placeholders::_2),
315         unzipParam);
316     close(zipFd);
317     return ret;
318 }
319 
Unzip(const std::string & srcFile,const std::string & destFile,OPTIONS options,std::shared_ptr<ZlibCallbackInfo> zlibCallbackInfo)320 bool Unzip(const std::string &srcFile, const std::string &destFile, OPTIONS options,
321     std::shared_ptr<ZlibCallbackInfo> zlibCallbackInfo)
322 {
323     if (zlibCallbackInfo == nullptr) {
324         APP_LOGE("zlibCallbackInfo is nullptr");
325         return false;
326     }
327     FilePath srcFileDir(srcFile);
328     FilePath destDir(destFile);
329     if ((destDir.Value().size() == 0) || FilePath::HasRelativePathBaseOnAPIVersion(destFile)) {
330         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_DEST_FILE_DISABLED);
331         return false;
332     }
333     if ((srcFileDir.Value().size() == 0) || FilePath::HasRelativePathBaseOnAPIVersion(srcFile)) {
334         APP_LOGI("srcFile isn't Exist");
335         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_SRC_FILE_DISABLED);
336         return false;
337     }
338     if (!FilePath::PathIsValid(srcFileDir)) {
339         APP_LOGI("srcFile invalid");
340         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_SRC_FILE_DISABLED);
341         return false;
342     }
343     if (FilePath::DirectoryExists(destDir)) {
344         if (!FilePath::PathIsWriteable(destDir)) {
345             APP_LOGI("FilePath::PathIsWriteable(destDir) fail");
346             zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_DEST_FILE_DISABLED);
347             return false;
348         }
349     } else {
350         APP_LOGI("destDir isn't path");
351         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_DEST_FILE_DISABLED);
352         return false;
353     }
354     auto innerTask = [srcFileDir, destDir, options, zlibCallbackInfo]() {
355         UnzipParam unzipParam {
356             .filterCB = ExcludeNoFilesFilter,
357             .logSkippedFiles = true
358         };
359         ErrCode err = UnzipWithFilterCallback(srcFileDir, destDir, options, unzipParam);
360         if (zlibCallbackInfo != nullptr) {
361             zlibCallbackInfo->OnZipUnZipFinish(err);
362         }
363     };
364     PostTask(innerTask);
365     return true;
366 }
367 
ZipWithFilterCallback(const FilePath & srcDir,const FilePath & destFile,const OPTIONS & options,FilterCallback filterCB)368 ErrCode ZipWithFilterCallback(const FilePath &srcDir, const FilePath &destFile,
369     const OPTIONS &options, FilterCallback filterCB)
370 {
371     FilePath destPath = destFile;
372     if (!FilePath::DirectoryExists(destPath.DirName())) {
373         APP_LOGE("The destPath not exist");
374         return ERR_ZLIB_DEST_FILE_DISABLED;
375     }
376     if (!FilePath::PathIsWriteable(destPath.DirName())) {
377         APP_LOGE("The destPath not writeable");
378         return ERR_ZLIB_DEST_FILE_DISABLED;
379     }
380 
381     if (!FilePath::PathIsValid(srcDir)) {
382         APP_LOGI("srcDir isn't Exist");
383         return ERR_ZLIB_SRC_FILE_DISABLED;
384     } else {
385         if (!FilePath::PathIsReadable(srcDir)) {
386             APP_LOGI("srcDir not readable");
387             return ERR_ZLIB_SRC_FILE_DISABLED;
388         }
389     }
390 
391     std::vector<FilePath> srcFile = {srcDir};
392     ZipParams params(srcFile, FilePath(destPath.CheckDestDirTail()));
393     params.SetFilterCallback(filterCB);
394     bool result = Zip(params, options);
395     if (result) {
396         return ERR_OK;
397     } else {
398         return ERR_ZLIB_DEST_FILE_DISABLED;
399     }
400 }
401 
ZipsWithFilterCallback(const std::vector<FilePath> & srcFiles,const FilePath & destFile,const OPTIONS & options,FilterCallback filterCB)402 ErrCode ZipsWithFilterCallback(const std::vector<FilePath> &srcFiles, const FilePath &destFile,
403     const OPTIONS &options, FilterCallback filterCB)
404 {
405     FilePath destPath = destFile;
406     if (!FilePath::DirectoryExists(destPath.DirName())) {
407         APP_LOGE("The destPath not exist");
408         return ERR_ZLIB_DEST_FILE_DISABLED;
409     }
410     if (!FilePath::PathIsWriteable(destPath.DirName())) {
411         APP_LOGE("The destPath not writeable");
412         return ERR_ZLIB_DEST_FILE_DISABLED;
413     }
414 
415     for (auto iter = srcFiles.begin(); iter != srcFiles.end(); ++iter) {
416         if (!FilePath::PathIsValid(*iter)) {
417             APP_LOGI("srcDir isn't Exist");
418             return ERR_ZLIB_SRC_FILE_DISABLED;
419         } else {
420             if (!FilePath::PathIsReadable(*iter)) {
421                 APP_LOGI("srcDir not readable");
422                 return ERR_ZLIB_SRC_FILE_DISABLED;
423             }
424         }
425     }
426 
427     ZipParams params(srcFiles, FilePath(destPath.CheckDestDirTail()));
428     params.SetFilterCallback(filterCB);
429     bool result = Zips(params, options);
430     if (result) {
431         return ERR_OK;
432     } else {
433         return ERR_ZLIB_DEST_FILE_DISABLED;
434     }
435 }
436 
Zip(const std::string & srcPath,const std::string & destPath,const OPTIONS & options,bool includeHiddenFiles,std::shared_ptr<ZlibCallbackInfo> zlibCallbackInfo)437 bool Zip(const std::string &srcPath, const std::string &destPath, const OPTIONS &options,
438     bool includeHiddenFiles, std::shared_ptr<ZlibCallbackInfo> zlibCallbackInfo)
439 {
440     if (zlibCallbackInfo == nullptr) {
441         return false;
442     }
443     FilePath srcDir(srcPath);
444     FilePath destFile(destPath);
445     APP_LOGD("srcDir=%{private}s, destFile=%{private}s", srcDir.Value().c_str(), destFile.Value().c_str());
446 
447     if ((srcDir.Value().size() == 0) || FilePath::HasRelativePathBaseOnAPIVersion(srcPath)) {
448         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_SRC_FILE_DISABLED);
449         return false;
450     }
451     if ((destFile.Value().size() == 0) || FilePath::HasRelativePathBaseOnAPIVersion(destPath)) {
452         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_DEST_FILE_DISABLED);
453         return false;
454     }
455 
456     auto innerTask = [srcDir, destFile, includeHiddenFiles, zlibCallbackInfo, options]() {
457         if (includeHiddenFiles) {
458             ErrCode err = ZipWithFilterCallback(srcDir, destFile, options, ExcludeNoFilesFilter);
459             if (zlibCallbackInfo != nullptr) {
460                 zlibCallbackInfo->OnZipUnZipFinish(err);
461             }
462         } else {
463             ErrCode err = ZipWithFilterCallback(srcDir, destFile, options, ExcludeHiddenFilesFilter);
464             if (zlibCallbackInfo != nullptr) {
465                 zlibCallbackInfo->OnZipUnZipFinish(err);
466             }
467         }
468     };
469 
470     PostTask(innerTask);
471     return true;
472 }
473 
ZipFileIsValid(const std::string & srcFile)474 bool ZipFileIsValid(const std::string &srcFile)
475 {
476     if ((srcFile.size() == 0) || FilePath::HasRelativePathBaseOnAPIVersion(srcFile)) {
477         APP_LOGE("srcFile len is 0 or ../");
478         return false;
479     }
480     if (!FilePathCheckValid(srcFile)) {
481         APP_LOGE("FilePathCheckValid return false");
482         return false;
483     }
484     FilePath srcFileDir(srcFile);
485     if (!FilePath::PathIsValid(srcFileDir)) {
486         APP_LOGE("PathIsValid return false");
487         return false;
488     }
489     if (!FilePath::PathIsReadable(srcFileDir)) {
490         APP_LOGE("PathIsReadable return false");
491         return false;
492     }
493     return true;
494 }
495 
GetOriginalSize(PlatformFile zipFd,int64_t & originalSize)496 ErrCode GetOriginalSize(PlatformFile zipFd, int64_t &originalSize)
497 {
498     ZipReader reader;
499     if (!reader.OpenFromPlatformFile(zipFd)) {
500         APP_LOGE("Failed to open, not ZIP format or damaged");
501         return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
502     }
503     int64_t totalSize = 0;
504     while (reader.HasMore()) {
505         if (!reader.OpenCurrentEntryInZip()) {
506             APP_LOGE("Failed to open the current file in zip");
507             return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
508         }
509         const FilePath &constEntryPath = reader.CurrentEntryInfo()->GetFilePath();
510         FilePath entryPath = constEntryPath;
511         if (reader.CurrentEntryInfo()->IsUnsafe()) {
512             APP_LOGE("Found an unsafe file in zip");
513             return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
514         }
515         totalSize += reader.CurrentEntryInfo()->GetOriginalSize();
516         if (!reader.AdvanceToNextEntry()) {
517             APP_LOGE("Failed to advance to the next file");
518             return ERR_ZLIB_SRC_FILE_FORMAT_ERROR;
519         }
520     }
521     originalSize = totalSize;
522     return ERR_OK;
523 }
524 
GetOriginalSize(const std::string & srcFile,int64_t & originalSize)525 ErrCode GetOriginalSize(const std::string &srcFile, int64_t &originalSize)
526 {
527     if (!ZipFileIsValid(srcFile)) {
528         return ERR_ZLIB_SRC_FILE_DISABLED;
529     }
530     PlatformFile zipFd = open(srcFile.c_str(), S_IREAD, O_CREAT);
531     if (zipFd == kInvalidPlatformFile) {
532         APP_LOGE("Failed to open file, errno: %{public}d, %{public}s", errno, strerror(errno));
533         return ERR_ZLIB_SRC_FILE_DISABLED;
534     }
535     ErrCode ret = GetOriginalSize(zipFd, originalSize);
536     close(zipFd);
537     return ret;
538 }
539 
Zips(const std::vector<std::string> & srcFiles,const std::string & destPath,const OPTIONS & options,bool includeHiddenFiles,std::shared_ptr<ZlibCallbackInfo> zlibCallbackInfo)540 bool Zips(const std::vector<std::string> &srcFiles, const std::string &destPath, const OPTIONS &options,
541     bool includeHiddenFiles, std::shared_ptr<ZlibCallbackInfo> zlibCallbackInfo)
542 {
543     if (zlibCallbackInfo == nullptr) {
544         return false;
545     }
546     if (FilePath::HasRelativePathBaseOnAPIVersion(srcFiles)) {
547         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_SRC_FILE_DISABLED);
548         return false;
549     }
550     std::vector<FilePath> srcFilesPath;
551     for (auto iter = srcFiles.begin(); iter != srcFiles.end(); ++iter) {
552         FilePath srcFile(*iter);
553         if (srcFile.Value().size() == 0) {
554             zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_SRC_FILE_DISABLED);
555             return false;
556         }
557         srcFilesPath.push_back(srcFile);
558     }
559     FilePath destFile(destPath);
560     if ((destFile.Value().size() == 0) || FilePath::HasRelativePathBaseOnAPIVersion(destPath)) {
561         zlibCallbackInfo->OnZipUnZipFinish(ERR_ZLIB_DEST_FILE_DISABLED);
562         return false;
563     }
564 
565     auto innerTask = [srcFilesPath, destFile, includeHiddenFiles, zlibCallbackInfo, options]() {
566         if (includeHiddenFiles) {
567             ErrCode err = ZipsWithFilterCallback(srcFilesPath, destFile, options, ExcludeNoFilesFilter);
568             if (zlibCallbackInfo != nullptr) {
569                 zlibCallbackInfo->OnZipUnZipFinish(err);
570             }
571         } else {
572             ErrCode err = ZipsWithFilterCallback(srcFilesPath, destFile, options, ExcludeHiddenFilesFilter);
573             if (zlibCallbackInfo != nullptr) {
574                 zlibCallbackInfo->OnZipUnZipFinish(err);
575             }
576         }
577     };
578 
579     PostTask(innerTask);
580     return true;
581 }
582 }  // namespace LIBZIP
583 }  // namespace AppExecFwk
584 }  // namespace OHOS
585