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