1 /*
2 * Copyright (c) 2021 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 "file_manager.h"
17 #include <algorithm>
18 #include "compression_parser.h"
19 #include <iostream>
20 #include "factory_resource_compiler.h"
21 #include "file_entry.h"
22 #include "key_parser.h"
23 #include "reference_parser.h"
24 #include "resource_directory.h"
25 #include "resource_util.h"
26 #include "restool_errors.h"
27 #include "resource_module.h"
28
29 namespace OHOS {
30 namespace Global {
31 namespace Restool {
32 using namespace std;
ScanModules(const vector<string> & inputs,const string & output,const bool isHar)33 uint32_t FileManager::ScanModules(const vector<string> &inputs, const string &output, const bool isHar)
34 {
35 vector<pair<ResType, string>> noBaseResource;
36 for (auto input : inputs) {
37 if (ScanModule(input, output) != RESTOOL_SUCCESS) {
38 return RESTOOL_ERROR;
39 }
40 CheckAllItems(noBaseResource);
41 }
42 if (!noBaseResource.empty()) {
43 ResourceUtil::PrintWarningMsg(noBaseResource);
44 }
45 return isHar ? RESTOOL_SUCCESS : ParseReference(output);
46 }
47
MergeResourceItem(const map<int64_t,vector<ResourceItem>> & resourceInfos)48 uint32_t FileManager::MergeResourceItem(const map<int64_t, vector<ResourceItem>> &resourceInfos)
49 {
50 return ResourceModule::MergeResourceItem(items_, resourceInfos);
51 }
52
53 // below private founction
ScanModule(const string & input,const string & output)54 uint32_t FileManager::ScanModule(const string &input, const string &output)
55 {
56 ResourceModule resourceModule(input, output, moduleName_);
57 if (resourceModule.ScanResource() != RESTOOL_SUCCESS) {
58 return RESTOOL_ERROR;
59 }
60 MergeResourceItem(resourceModule.GetOwner());
61 return RESTOOL_SUCCESS;
62 }
63
ParseReference(const string & output)64 uint32_t FileManager::ParseReference(const string &output)
65 {
66 ReferenceParser referenceParser;
67 if (referenceParser.ParseRefInResources(items_, output) != RESTOOL_SUCCESS) {
68 return RESTOOL_ERROR;
69 }
70 return RESTOOL_SUCCESS;
71 }
72
CheckAllItems(vector<pair<ResType,string>> & noBaseResource)73 void FileManager::CheckAllItems(vector<pair<ResType, string>> &noBaseResource)
74 {
75 for (const auto &item : items_) {
76 bool found = any_of(item.second.begin(), item.second.end(), [](const auto &iter) {
77 return iter.GetLimitKey() == "base";
78 });
79 if (!found) {
80 auto firstItem = item.second.front();
81 bool ret = any_of(noBaseResource.begin(), noBaseResource.end(), [firstItem](const auto &iterItem) {
82 return (firstItem.GetResType() == iterItem.first) &&
83 (firstItem.GetName() == iterItem.second);
84 });
85 if (!ret) {
86 noBaseResource.push_back(make_pair(firstItem.GetResType(), firstItem.GetName()));
87 }
88 }
89 }
90 }
91
ScaleIcons(const string & output,const std::map<std::string,std::set<uint32_t>> & iconMap)92 bool FileManager::ScaleIcons(const string &output, const std::map<std::string, std::set<uint32_t>> &iconMap)
93 {
94 if (!CompressionParser::GetCompressionParser()->ScaleIconEnable()) {
95 cout << "Info: scale icon is not enable." << endl;
96 return true;
97 }
98 std::set<int64_t> allIconIds;
99 for (auto &it : iconMap) {
100 if (it.first != "icon") {
101 continue;
102 }
103 allIconIds.insert(it.second.begin(), it.second.end());
104 }
105 if (allIconIds.size() == 0) {
106 cout << "Info: no icons need to scale, icon ids size is 0." << endl;
107 return true;
108 }
109 for (auto &id : allIconIds) {
110 std::map<int64_t, std::vector<ResourceItem>>::iterator iter = items_.find(id);
111 if (iter == items_.end()) {
112 continue;
113 }
114 for (auto &item : iter->second) {
115 if (!ScaleIcon(output, item)) {
116 return false;
117 }
118 }
119 }
120 return true;
121 }
122
ScaleIcon(const string & output,ResourceItem & item)123 bool FileManager::ScaleIcon(const string &output, ResourceItem &item)
124 {
125 std::string media = "media";
126 // item's data is short path for icon file, such as "entry/resources/base/media/app_icon.png"
127 const string currentData(reinterpret_cast<const char *>(item.GetData()), item.GetDataLength());
128 auto outIndex = currentData.find_last_of(SEPARATOR);
129 if (outIndex == string::npos) {
130 cerr << "Error: ScaleIcon invalid output name: " << currentData << endl;
131 return false;
132 }
133 // get current output file name and full path
134 string fileName = currentData.substr(outIndex + 1);
135 FileEntry::FilePath fullFilePath = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(item.GetLimitKey())
136 .Append(media).Append(fileName);
137 if (fullFilePath.GetExtension() == JSON_EXTENSION) {
138 cout << "Info: can't scale media json file." << endl;
139 return true;
140 }
141 const string fullOutPath = fullFilePath.GetPath();
142 // delete current output file
143 if (!ResourceUtil::RmoveFile(fullOutPath)) {
144 cout << "Error: ScaleIcon RmoveFile failed: " << fullOutPath << endl;
145 return false;
146 }
147 // get origin icon output full path with the origin icon file name in src
148 std::string dst = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(item.GetLimitKey()).Append(media)
149 .Append(item.GetName()).GetPath();
150 // the origin full file in src
151 std::string scaleDst = item.GetFilePath();
152 // scale icon
153 if (!CompressionParser::GetCompressionParser()->CheckAndScaleIcon(item.GetFilePath(), dst, scaleDst)) {
154 return false;
155 }
156 // compress scaled icon
157 if (!CompressionParser::GetCompressionParser()->CopyAndTranscode(scaleDst, dst)) {
158 return false;
159 }
160 string newFileName = FileEntry::FilePath(dst).GetFilename();
161 std::string newData = moduleName_ + SEPARATOR + RESOURCES_DIR + SEPARATOR + item.GetLimitKey() + SEPARATOR + media
162 + SEPARATOR + newFileName;
163 if (!item.SetData(reinterpret_cast<const int8_t *>(newData.c_str()), newData.length())) {
164 cerr << "Error: ScaleIcon resource item set data fail, data: " << newData << NEW_LINE_PATH
165 << item.GetFilePath() << endl;
166 return false;
167 }
168 return true;
169 }
170 }
171 }
172 }
173