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 "resource_compiler_factory.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(scanHap_) != 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
SetScanHap(bool state)123 void FileManager::SetScanHap(bool state)
124 {
125 scanHap_ = state;
126 }
127
ScaleIcon(const string & output,ResourceItem & item)128 bool FileManager::ScaleIcon(const string &output, ResourceItem &item)
129 {
130 std::string media = "media";
131 // item's data is short path for icon file, such as "entry/resources/base/media/app_icon.png"
132 const string currentData(reinterpret_cast<const char *>(item.GetData()), item.GetDataLength());
133 auto outIndex = currentData.find_last_of(SEPARATOR);
134 if (outIndex == string::npos) {
135 PrintError(GetError(ERR_CODE_INVALID_OUTPUT).FormatCause(currentData.c_str()));
136 return false;
137 }
138 // get current output file name and full path
139 string fileName = currentData.substr(outIndex + 1);
140 FileEntry::FilePath fullFilePath = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(item.GetLimitKey())
141 .Append(media).Append(fileName);
142 if (fullFilePath.GetExtension() == JSON_EXTENSION) {
143 cout << "Info: can't scale media json file." << endl;
144 return true;
145 }
146 const string fullOutPath = fullFilePath.GetPath();
147 // delete current output file
148 if (!ResourceUtil::RmoveFile(fullOutPath)) {
149 return false;
150 }
151 // get origin icon output full path with the origin icon file name in src
152 std::string dst = FileEntry::FilePath(output).Append(RESOURCES_DIR).Append(item.GetLimitKey()).Append(media)
153 .Append(item.GetName()).GetPath();
154 // the origin full file in src
155 std::string scaleDst = item.GetFilePath();
156 // scale icon
157 if (!CompressionParser::GetCompressionParser()->CheckAndScaleIcon(item.GetFilePath(), dst, scaleDst)) {
158 return false;
159 }
160 // compress scaled icon
161 if (!CompressionParser::GetCompressionParser()->CopyAndTranscode(scaleDst, dst)) {
162 return false;
163 }
164 string newFileName = FileEntry::FilePath(dst).GetFilename();
165 std::string newData = moduleName_ + SEPARATOR + RESOURCES_DIR + SEPARATOR + item.GetLimitKey() + SEPARATOR + media
166 + SEPARATOR + newFileName;
167 if (!item.SetData(reinterpret_cast<const int8_t *>(newData.c_str()), newData.length())) {
168 std::string msg = "item data is null, resource name: " + item.GetName();
169 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause(msg.c_str()).SetPosition(item.GetFilePath()));
170 return false;
171 }
172 return true;
173 }
174 }
175 }
176 }
177