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 26namespace OHOS { 27namespace AppPackingTool { 28namespace { 29const std::string RESOURCE_PATH = "resources/base/profile/"; 30} 31 32ZipUtils::ZipUtils() 33{} 34 35ZipUtils::~ZipUtils() 36{} 37 38int32_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 57int32_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 72bool 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 120bool 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 167bool 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 += std::string(buffer); 213 } while (readLen > 0); 214 unzCloseCurrentFile(unzipFile); 215 unzClose(unzipFile); 216 return true; 217} 218 219bool 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 247bool 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 267bool 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