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 ¶ms, const OPTIONS &options)
132 {
133 const std::vector<std::pair<FilePath, FilePath>> *filesToAdd = ¶ms.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 ¶ms, 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 ¶ms, 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 ¶ms, const OPTIONS &options)
221 {
222 const std::vector<std::pair<FilePath, FilePath>> *filesToAdd = ¶ms.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