• 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 "version_normalize.h"
17 
18 #include "hap_packager.h"
19 #include "hqf_packager.h"
20 #include "hsp_packager.h"
21 #include "json/json_utils.h"
22 #include "json/normalize_version_utils.h"
23 #include "json/pack_info.h"
24 #include "log.h"
25 #include "utils.h"
26 #include "zip_utils.h"
27 
28 namespace OHOS {
29 namespace AppPackingTool {
VersionNormalize(const std::map<std::string,std::string> & parameterMap,std::string & resultReceiver)30 VersionNormalize::VersionNormalize(const std::map<std::string, std::string> &parameterMap, std::string &resultReceiver)
31     : Packager(parameterMap, resultReceiver)
32 {}
33 
InitAllowedParam()34 int32_t VersionNormalize::InitAllowedParam()
35 {
36     allowedParameters_ = {
37         {}
38     };
39     return ERR_OK;
40 }
41 
PreProcess()42 int32_t VersionNormalize::PreProcess()
43 {
44     if (!IsOutDirectoryValid()) {
45         return ERR_INVALID_VALUE;
46     }
47     auto it = parameterMap_.find(Constants::PARAM_INPUT_LIST);
48     if (it == parameterMap_.end()) {
49         LOGE("Input input-list is empty.");
50         return ERR_INVALID_VALUE;
51     }
52     if (!CompatibleProcess(it->second, hspOrhapList_, Constants::HAP_SUFFIX, Constants::HSP_SUFFIX)) {
53             LOGE("Input input-list is invalid.");
54             return ERR_INVALID_VALUE;
55         }
56     if (hspOrhapList_.size() == 0) {
57         LOGE("Input input-list is empty.");
58         return ERR_INVALID_VALUE;
59     }
60 
61     it = parameterMap_.find(Constants::PARAM_VERSION_NAME);
62     std::regex pattern(Constants::VERSION_NAME_PATTERN);
63     if (it == parameterMap_.end()) {
64         LOGE("Input version-name is empty.");
65         return ERR_INVALID_VALUE;
66     } else if (!std::regex_match(it->second, pattern)) {
67         LOGE("Input version-name is not valid.");
68         return ERR_INVALID_VALUE;
69     }
70 
71     it = parameterMap_.find(Constants::PARAM_VERSION_CODE);
72     if (it == parameterMap_.end()) {
73         LOGE("Input version-code is empty.");
74         return ERR_INVALID_VALUE;
75     } else if (!Utils::IsPositiveInteger(it->second)) {
76         LOGE("Input version-code is invalid.");
77         return ERR_INVALID_VALUE;
78     }
79     return ERR_OK;
80 }
81 
VerifyModuleVersion(const NormalizeVersion & normalizeVersion,const int32_t & newVersionCode,const std::string & newVersionName)82 bool VersionNormalize::VerifyModuleVersion(const NormalizeVersion &normalizeVersion, const int32_t &newVersionCode,
83     const std::string &newVersionName)
84 {
85     if (normalizeVersion.originVersionCode > newVersionCode) {
86         LOGE("VersionNormalize failed, input version code less than module %s version code.",
87             normalizeVersion.moduleName.c_str());
88         return false;
89     } else if (normalizeVersion.originVersionCode == newVersionCode) {
90         LOGW("VersionNormalize warning: module %s version code not changed.", normalizeVersion.moduleName.c_str());
91     }
92     if (normalizeVersion.originVersionName == newVersionName) {
93         LOGW("VersionNormalize warning: module %s version name not changed.", normalizeVersion.moduleName.c_str());
94     }
95     return true;
96 }
97 
ModifyModuleJson(const std::string & moduleJsonPath,NormalizeVersion & normalizeVersion,const int32_t & newVersionCode,const std::string & newVersionName)98 bool VersionNormalize::ModifyModuleJson(const std::string &moduleJsonPath, NormalizeVersion &normalizeVersion,
99     const int32_t &newVersionCode, const std::string &newVersionName)
100 {
101     ModuleJson moduleJson;
102     if (!moduleJson.ParseFromFile(moduleJsonPath)) {
103         LOGE("Parse and modify module.json failed, parse module.json is null.");
104         return false;
105     }
106     if (!moduleJson.GetNormalizeVersion(normalizeVersion, true)) {
107         LOGE("Parse and modify module.json failed, write Json failed.");
108         return false;
109     }
110     if (!moduleJson.SetVersionCodeAndName(newVersionCode, newVersionName, true)) {
111         LOGE("Parse and modify module.json failed, json file not valid.");
112         return false;
113     }
114     if (!JsonUtils::StrToFile(moduleJson.ToString(), moduleJsonPath)) {
115         LOGE("Parse and modify module.json failed, write Json failed.");
116         return false;
117     }
118     return true;
119 }
120 
ModifyConfigJson(const std::string & configJsonPath,NormalizeVersion & normalizeVersion,const int32_t & newVersionCode,const std::string & newVersionName)121 bool VersionNormalize::ModifyConfigJson(const std::string &configJsonPath, NormalizeVersion &normalizeVersion,
122     const int32_t &newVersionCode, const std::string &newVersionName)
123 {
124     ModuleJson configJson;
125     if (!configJson.ParseFromFile(configJsonPath)) {
126         LOGE("Parse and modify config.json failed, parse json is null.");
127         return false;
128     }
129     if (!configJson.GetNormalizeVersion(normalizeVersion, false)) {
130         LOGE("Parse and modify config.json failed, json file not valid.");
131         return false;
132     }
133     if (!configJson.SetVersionCodeAndName(newVersionCode, newVersionName, false)) {
134         LOGE("Parse and modify config.json failed, json file not valid.");
135         return false;
136     }
137     if (!JsonUtils::StrToFile(configJson.ToString(), configJsonPath)) {
138         LOGE("Parse and modify config.json failed, writeJson failed.");
139         return false;
140     }
141     return true;
142 }
143 
ModifyPackInfo(const std::string & packInfoPath,const int32_t & newVersionCode,const std::string & newVersionName)144 bool VersionNormalize::ModifyPackInfo(const std::string &packInfoPath, const int32_t &newVersionCode,
145     const std::string &newVersionName)
146 {
147     PackInfo packInfo;
148     if (!packInfo.ParseFromFile(packInfoPath)) {
149         LOGW("Parse and modify packInfo failed, json format invalid.");
150         return false;
151     }
152     if (!packInfo.SetVersionCode(newVersionCode)) {
153         LOGW("Parse and modify packInfo failed, version code invalid.");
154         return false;
155     }
156     if (!packInfo.SetVersionName(newVersionName)) {
157         LOGW("Parse and modify packInfo failed, version name invalid.");
158         return false;
159     }
160 
161     if (!JsonUtils::StrToFile(packInfo.ToString(), packInfoPath)) {
162         LOGW("Parse and modify packInfo failed, writeJson failed.");
163         return false;
164     }
165     return true;
166 }
167 
CompressDirToHap(const std::string & sourceDir,const std::string & zipFilePath)168 bool VersionNormalize::CompressDirToHap(const std::string &sourceDir, const std::string &zipFilePath)
169 {
170     std::map<std::string, std::string> parameterMap;
171     std::string resultReceiver = "";
172     parameterMap[Constants::PARAM_OUT_PATH] = zipFilePath;
173     std::unique_ptr<Packager> packager = nullptr;
174     for (const auto& entry : fs::directory_iterator(fs::path(sourceDir))) {
175         std::string fileName = entry.path().filename().string();
176         std::string filePath = entry.path().string();
177         if (fileName == Constants::ETS_PATH) {
178             parameterMap[Constants::PARAM_ETS_PATH] = filePath;
179         } else if (fileName == Constants::HNP_PATH) {
180             parameterMap[Constants::PARAM_HNP_PATH] = filePath;
181         } else if (fileName == Constants::LIB_PATH) {
182             parameterMap[Constants::PARAM_LIB_PATH] = filePath;
183         } else if (fileName == Constants::AN_PATH) {
184             parameterMap[Constants::PARAM_AN_PATH] = filePath;
185         } else if (fileName == Constants::AP_PATH) {
186             parameterMap[Constants::PARAM_AP_PATH] = filePath;
187         } else if (fileName == Constants::RESOURCES_PATH) {
188             parameterMap[Constants::PARAM_RESOURCES_PATH] = filePath;
189         } else if (fileName == Constants::JS_PATH) {
190             parameterMap[Constants::PARAM_JS_PATH] = filePath;
191         } else if (fileName == Constants::ASSETS_PATH) {
192             parameterMap[Constants::PARAM_ASSETS_PATH] = filePath;
193         } else if (fileName == Constants::SO_DIR) {
194             parameterMap[Constants::PARAM_MAPLE_SO_DIR] = filePath;
195         } else if (fileName == Constants::SHARED_LIBS_DIR) {
196             parameterMap[Constants::PARAM_SHAREDLIBS_PATH] = filePath;
197         } else if (fileName == Constants::CONFIG_JSON) {
198             parameterMap[Constants::PARAM_JSON_PATH] = filePath;
199         } else if (fileName == Constants::MODULE_JSON) {
200             parameterMap[Constants::PARAM_JSON_PATH] = filePath;
201         } else if (fileName == Constants::RESOURCES_INDEX) {
202             parameterMap[Constants::PARAM_INDEX_PATH] = filePath;
203         } else if (fileName == Constants::PACK_INFO) {
204             parameterMap[Constants::PARAM_PACK_INFO_PATH] = filePath;
205         } else if (fileName == Constants::RPCID_SC) {
206             parameterMap[Constants::PARAM_RPCID_PATH] = filePath;
207         }
208     }
209     if (Utils::EndsWith(zipFilePath, Constants::HAP_SUFFIX)) {
210         packager = std::make_unique<HapPackager>(parameterMap, resultReceiver);
211     } else if (Utils::EndsWith(zipFilePath, Constants::HSP_SUFFIX)) {
212         packager = std::make_unique<HspPackager>(parameterMap, resultReceiver);
213     }
214 
215     if (packager == nullptr || packager->PreProcess() != ERR_OK || packager->Process() != ERR_OK) {
216         return false;
217     }
218     return true;
219 }
220 
221 
ProcessJsonFiles(const std::string & tempPath,std::list<NormalizeVersion> & normalizeVersionList,const int32_t & versionCode,const std::string & versionName)222 bool VersionNormalize::ProcessJsonFiles(const std::string &tempPath, std::list<NormalizeVersion> &normalizeVersionList,
223     const int32_t &versionCode, const std::string &versionName)
224 {
225     NormalizeVersion normalizeVersion;
226     std::string moduleJsonPath = tempPath + Constants::LINUX_FILE_SEPARATOR + Constants::MODULE_JSON;
227     std::string configJsonPath = tempPath + Constants::LINUX_FILE_SEPARATOR + Constants::CONFIG_JSON;
228     std::string packInfoPath = tempPath + Constants::LINUX_FILE_SEPARATOR + Constants::PACK_INFO;
229 
230     bool isModuleFileExists = fs::exists(moduleJsonPath);
231     bool isConfigFileExists = fs::exists(configJsonPath);
232     bool isPackInfoFileExists = fs::exists(packInfoPath);
233     if (isModuleFileExists == isConfigFileExists) {
234         LOGE("VersionNormalize failed, invalid hap structure.");
235         return false;
236     }
237 
238     bool modifyJsonSuccess = false;
239     if (isModuleFileExists) {
240         modifyJsonSuccess = ModifyModuleJson(moduleJsonPath, normalizeVersion, versionCode, versionName);
241     } else {
242         modifyJsonSuccess = ModifyConfigJson(configJsonPath, normalizeVersion, versionCode, versionName);
243     }
244 
245     if (!modifyJsonSuccess) {
246         normalizeVersionList.push_back(normalizeVersion);
247         return false;
248     }
249 
250     if (isPackInfoFileExists) {
251         if (!ModifyPackInfo(packInfoPath, versionCode, versionName)) {
252             normalizeVersionList.push_back(normalizeVersion);
253             return false;
254         }
255     }
256 
257     if (!VerifyModuleVersion(normalizeVersion, versionCode, versionName)) {
258         return false;
259     }
260     normalizeVersionList.push_back(normalizeVersion);
261     return true;
262 }
263 
Process()264 int32_t VersionNormalize::Process()
265 {
266     std::string outPath = parameterMap_.at(Constants::PARAM_OUT_PATH);
267     std::string tempPath = outPath + Constants::LINUX_FILE_SEPARATOR + Constants::COMPRESSOR_VERSIONNORMALIZE_TEMP_DIR
268         + Utils::GenerateUUID();
269     int32_t versionCode = std::stoi(parameterMap_.at(Constants::PARAM_VERSION_CODE));
270     std::string versionName = parameterMap_.at(Constants::PARAM_VERSION_NAME);
271     std::list<NormalizeVersion> normalizeVersionList;
272 
273     for (const std::string& path : hspOrhapList_) {
274         ZipUtils::Unzip(path, tempPath);
275         if (!ProcessJsonFiles(tempPath, normalizeVersionList, versionCode, versionName)) {
276             Utils::ForceRemoveDirectory(tempPath);
277             continue;
278         }
279         if (!CompressDirToHap(tempPath,
280             outPath + Constants::LINUX_FILE_SEPARATOR + fs::path(path).filename().string())) {
281             Utils::ForceRemoveDirectory(tempPath);
282             continue;
283         }
284         Utils::ForceRemoveDirectory(tempPath);
285     }
286 
287     if (!JsonUtils::StrToFile(NormalizeVersionUtils::ArrayToString(normalizeVersionList), outPath +
288         Constants::LINUX_FILE_SEPARATOR + Constants::VERSION_RECORD)) {
289         LOGE("WriteVersionRecord failed.");
290         return ERR_INVALID_VALUE;
291     }
292     return ERR_OK;
293 }
294 
PostProcess()295 int32_t VersionNormalize::PostProcess()
296 {
297     return ERR_OK;
298 }
299 } // namespace AppPackingTool
300 } // namespace OHOS