• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_utils.h"
17 
18 #include <algorithm>
19 #include <cstring>
20 #include <map>
21 #include <iostream>
22 
23 #include "log.h"
24 #include "utils.h"
25 
26 namespace OHOS {
27 namespace AppPackingTool {
28 namespace {
29 const std::string RESOURCE_PATH = "resources/base/profile/";
30 }
31 
ZipUtils()32 ZipUtils::ZipUtils()
33 {}
34 
~ZipUtils()35 ZipUtils::~ZipUtils()
36 {}
37 
Zip(const std::string & filePath,const std::string & zipFilePath,const std::string & zipPath,const ZipLevel & zipLevel,const int32_t & append)38 int32_t ZipUtils::Zip(const std::string& filePath, const std::string& zipFilePath,
39     const std::string& zipPath, const ZipLevel& zipLevel, const int32_t& append)
40 {
41     ZipWrapper zipWrapper(zipFilePath);
42     if (zipWrapper.Open(append) != ZIP_ERR_SUCCESS) {
43         LOGE("ZipWrapper Open failed!");
44         return ZIP_ERR_FAILURE;
45     }
46     if (zipLevel != ZipLevel::ZIP_LEVEL_DEFAULT) {
47         zipWrapper.SetZipLevel(zipLevel);
48     }
49     int32_t ret = zipWrapper.AddFileOrDirectoryToZip(filePath, zipPath);
50     if (ret != ZIP_ERR_SUCCESS) {
51         LOGE("ZipWrapper AddFileOrDirectoryToZip failed!");
52     }
53     zipWrapper.Close();
54     return ret;
55 }
56 
Unzip(const std::string & zipPath,const std::string & filePath)57 int32_t ZipUtils::Unzip(const std::string& zipPath, const std::string& filePath)
58 {
59     UnzipWrapper unzipWrapper(zipPath);
60     if (unzipWrapper.Open() != ZIP_ERR_SUCCESS) {
61         LOGE("UnzipWrapper Open failed!");
62         return ZIP_ERR_FAILURE;
63     }
64     int32_t ret = unzipWrapper.UnzipFile(filePath);
65     if (ret != ZIP_ERR_SUCCESS) {
66         LOGE("UnzipWrapper UnzipFile failed!");
67     }
68     unzipWrapper.Close();
69     return ret;
70 }
71 
IsFileExistsInZip(const std::string & zipFilePath,const std::string & filename)72 bool ZipUtils::IsFileExistsInZip(const std::string& zipFilePath, const std::string& filename)
73 {
74     fs::path fsZipFilePath(zipFilePath);
75     if (!fs::is_regular_file(fsZipFilePath)) {
76         LOGE("Zip file is not a regular file!");
77         return false;
78     }
79     unzFile unzipFile = unzOpen64(zipFilePath.c_str());
80     if (unzipFile == nullptr) {
81         LOGE("Open zip file failed! zipFilePath=%s", zipFilePath.c_str());
82         return false;
83     }
84     unz_global_info64 unzGlobalInfo;
85     if (unzGetGlobalInfo64(unzipFile, &unzGlobalInfo) != UNZ_OK) {
86         LOGE("Get zip global info! zipFilePath=%s", zipFilePath.c_str());
87         unzClose(unzipFile);
88         return false;
89     }
90     char filePathInZip[MAX_ZIP_BUFFER_SIZE] = {0};
91     unz_file_info64 fileInfo;
92     int ret = 0;
93     bool isExist = false;
94     for (size_t i = 0; i < unzGlobalInfo.number_entry; ++i) {
95         if (unzGetCurrentFileInfo64(unzipFile, &fileInfo, filePathInZip, MAX_ZIP_BUFFER_SIZE, NULL, 0, NULL, 0) !=
96             UNZ_OK) {
97             LOGE("Get current file info in zip failed!");
98             break;
99         }
100         std::string strFilePathInZip(filePathInZip);
101         if (fileInfo.external_fa != ZIP_FILE_ATTR_DIRECTORY && strFilePathInZip.length() >= filename.length()) {
102             std::transform(strFilePathInZip.begin(), strFilePathInZip.end(), strFilePathInZip.begin(), ::tolower);
103             if (strFilePathInZip.compare(filename) == 0) {
104                 isExist = true;
105                 break;
106             }
107         }
108         ret = unzGoToNextFile(unzipFile);
109         if (ret == UNZ_END_OF_LIST_OF_FILE) {
110             break;
111         } else if (ret != UNZ_OK) {
112             LOGE("Go to next file in zip failed!");
113             break;
114         }
115     }
116     unzClose(unzipFile);
117     return isExist;
118 }
119 
IsFileNameExistsInZip(const std::string & zipFilePath,const std::string & filename)120 bool ZipUtils::IsFileNameExistsInZip(const std::string& zipFilePath, const std::string& filename)
121 {
122     fs::path fsZipFilePath(zipFilePath);
123     if (!fs::is_regular_file(fsZipFilePath)) {
124         LOGE("Zip file is not a regular file!");
125         return false;
126     }
127     unzFile unzipFile = unzOpen64(zipFilePath.c_str());
128     if (unzipFile == nullptr) {
129         LOGE("Open zip file failed! zipFilePath=%s", zipFilePath.c_str());
130         return false;
131     }
132     unz_global_info64 unzGlobalInfo;
133     if (unzGetGlobalInfo64(unzipFile, &unzGlobalInfo) != UNZ_OK) {
134         LOGE("Get zip global info! zipFilePath=%s", zipFilePath.c_str());
135         unzClose(unzipFile);
136         return false;
137     }
138     char filePathInZip[MAX_ZIP_BUFFER_SIZE] = {0};
139     unz_file_info64 fileInfo;
140     int ret = 0;
141     bool isExist = false;
142     for (size_t i = 0; i < unzGlobalInfo.number_entry; ++i) {
143         if (unzGetCurrentFileInfo64(unzipFile, &fileInfo, filePathInZip, MAX_ZIP_BUFFER_SIZE, NULL, 0, NULL, 0) !=
144             UNZ_OK) {
145             LOGE("Get current file info in zip failed!");
146             break;
147         }
148         std::string strFilePathInZip(filePathInZip);
149         if (fileInfo.external_fa != ZIP_FILE_ATTR_DIRECTORY && strFilePathInZip.length() >= filename.length()) {
150             if (strFilePathInZip.substr(strFilePathInZip.length() - filename.length()).compare(filename) == 0) {
151                 isExist = true;
152                 break;
153             }
154         }
155         ret = unzGoToNextFile(unzipFile);
156         if (ret == UNZ_END_OF_LIST_OF_FILE) {
157             break;
158         } else if (ret != UNZ_OK) {
159             LOGE("Go to next file in zip failed!");
160             break;
161         }
162     }
163     unzClose(unzipFile);
164     return isExist;
165 }
166 
GetFileContentFromZip(const std::string & zipFilePath,const std::string & filename,std::string & fileContent)167 bool ZipUtils::GetFileContentFromZip(const std::string& zipFilePath, const std::string& filename,
168     std::string& fileContent)
169 {
170     fs::path fsZipFilePath(zipFilePath);
171     if (!fs::is_regular_file(fsZipFilePath)) {
172         LOGE("Zip file is not a regular file!");
173         return false;
174     }
175     unzFile unzipFile = unzOpen64(zipFilePath.c_str());
176     if (unzipFile == nullptr) {
177         LOGE("Open zip file failed! zipFilePath=%s", zipFilePath.c_str());
178         return false;
179     }
180     if (unzLocateFile(unzipFile, filename.c_str(), 0) != UNZ_OK) {
181         LOGE("Locate file failed! filename=%s", filename.c_str());
182         unzClose(unzipFile);
183         return false;
184     }
185     unz_file_info64 fileInfo;
186     char filePathInZip[MAX_ZIP_BUFFER_SIZE] = {0};
187     if (unzGetCurrentFileInfo64(unzipFile, &fileInfo, filePathInZip, MAX_ZIP_BUFFER_SIZE, NULL, 0, NULL, 0) !=
188         UNZ_OK) {
189         LOGE("Get current file info in zip failed! filename=%s", filename.c_str());
190         unzClose(unzipFile);
191         return false;
192     }
193     if (unzOpenCurrentFile(unzipFile) != UNZ_OK) {
194         LOGE("Open current file in zip failed! filename=%s", filename.c_str());
195         unzClose(unzipFile);
196         return false;
197     }
198     char buffer[MAX_ZIP_BUFFER_SIZE];
199     int readLen = 0;
200     fileContent = "";
201     do {
202         std::fill_n(buffer, MAX_ZIP_BUFFER_SIZE, '\0');
203         readLen = unzReadCurrentFile(unzipFile, buffer, MAX_ZIP_BUFFER_SIZE);
204         if (readLen < 0) {
205             LOGE("Read current file in zip failed! filename=%s", filename.c_str());
206             unzCloseCurrentFile(unzipFile);
207             unzClose(unzipFile);
208             return false;
209         } else if (readLen == 0) {
210             break;
211         }
212         fileContent.append(buffer, 0, readLen);
213     } while (readLen > 0);
214     unzCloseCurrentFile(unzipFile);
215     unzClose(unzipFile);
216     return true;
217 }
218 
GetUnzipCurrentFileContent(unzFile & unzipFile,std::string & fileContent)219 bool ZipUtils::GetUnzipCurrentFileContent(unzFile& unzipFile, std::string& fileContent)
220 {
221     if (unzipFile == nullptr) {
222         return false;
223     }
224     if (unzOpenCurrentFile(unzipFile) != UNZ_OK) {
225         LOGE("Open current file in zip failed!");
226         return false;
227     }
228     char buffer[MAX_ZIP_BUFFER_SIZE];
229     int readLen = 0;
230     fileContent = "";
231     do {
232         std::fill_n(buffer, MAX_ZIP_BUFFER_SIZE, '\0');
233         readLen = unzReadCurrentFile(unzipFile, buffer, MAX_ZIP_BUFFER_SIZE);
234         if (readLen < 0) {
235             LOGE("Read current file in zip failed!");
236             unzCloseCurrentFile(unzipFile);
237             return false;
238         } else if (readLen == 0) {
239             break;
240         }
241         fileContent += std::string(buffer);
242     } while (readLen > 0);
243     unzCloseCurrentFile(unzipFile);
244     return true;
245 }
246 
AddToResourceMap(unzFile & unzipFile,const std::string & filePathInZip,std::map<std::string,std::string> & resourceMap)247 bool ZipUtils::AddToResourceMap(unzFile& unzipFile, const std::string& filePathInZip,
248     std::map<std::string, std::string>& resourceMap)
249 {
250     if (unzipFile == nullptr) {
251         LOGE("zip file not open!");
252         return false;
253     }
254     if (filePathInZip.find(RESOURCE_PATH) != std::string::npos) {
255         std::string fileName = Utils::ReplaceAll(filePathInZip, RESOURCE_PATH, "");
256         std::string fileContent;
257         if (!GetUnzipCurrentFileContent(unzipFile, fileContent)) {
258             LOGE("Get current file content failed! filename=%s", filePathInZip.c_str());
259             return false;
260         } else {
261             resourceMap.emplace(fileName, fileContent);
262         }
263     }
264     return true;
265 }
266 
GetResourceMapFromZip(const std::string & zipFilePath,std::map<std::string,std::string> & resourceMap)267 bool ZipUtils::GetResourceMapFromZip(const std::string& zipFilePath, std::map<std::string, std::string>& resourceMap)
268 {
269     fs::path fsZipFilePath(zipFilePath);
270     if (!fs::is_regular_file(fsZipFilePath)) {
271         LOGE("Zip file is not a regular file!");
272         return false;
273     }
274     unzFile unzipFile = unzOpen64(zipFilePath.c_str());
275     if (unzipFile == nullptr) {
276         LOGE("Open zip file failed! zipFilePath=%s", zipFilePath.c_str());
277         return false;
278     }
279     unz_global_info64 unzGlobalInfo;
280     if (unzGetGlobalInfo64(unzipFile, &unzGlobalInfo) != UNZ_OK) {
281         LOGE("Get zip global info! zipFilePath=%s", zipFilePath.c_str());
282         unzClose(unzipFile);
283         return false;
284     }
285     char filePathInZip[MAX_ZIP_BUFFER_SIZE] = {0};
286     unz_file_info64 fileInfo;
287     int ret = 0;
288     for (size_t i = 0; i < unzGlobalInfo.number_entry; ++i) {
289         if (unzGetCurrentFileInfo64(unzipFile, &fileInfo, filePathInZip, MAX_ZIP_BUFFER_SIZE, NULL, 0, NULL, 0) !=
290             UNZ_OK) {
291             LOGE("Get current file info in zip failed!");
292             break;
293         }
294         std::string strFilePathInZip(filePathInZip);
295         if (fileInfo.external_fa != ZIP_FILE_ATTR_DIRECTORY && strFilePathInZip.length() > RESOURCE_PATH.length()) {
296             AddToResourceMap(unzipFile, strFilePathInZip, resourceMap);
297         }
298         ret = unzGoToNextFile(unzipFile);
299         if (ret == UNZ_END_OF_LIST_OF_FILE) {
300             break;
301         } else if (ret != UNZ_OK) {
302             LOGE("Go to next file in zip failed!");
303             break;
304         }
305     }
306     unzClose(unzipFile);
307     return true;
308 }
309 } // namespace AppPackingTool
310 } // namespace OHOS
311