1 /*
2 * Copyright (c) 2022 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 "print_utils.h"
17
18 #include <fcntl.h>
19 #include "ability.h"
20 #include "print_constant.h"
21 #include "print_log.h"
22 #include "securec.h"
23 #include <chrono>
24 #include <sstream>
25 #include <cstdlib>
26 #include <ctime>
27 #include <random>
28
29 namespace OHOS::Print {
30
31 using json = nlohmann::json;
32
33 std::mutex PrintUtils::instanceLock_;
34
35 static const std::string LAUNCH_PARAMETER_DOCUMENT_NAME = "documentName";
36 static const std::string LAUNCH_PARAMETER_PRINT_ATTRIBUTE = "printAttributes";
37
38 static std::map<uint32_t, std::string> jobStateMap_;
39 const std::string GLOBAL_ID_DELIMITER = ":";
40 const std::string EXTENSION_CID_DELIMITER = ":";
41 const std::string TASK_EVENT_DELIMITER = "-";
42 const int32_t DEFAULT_FD = 99;
43 const int32_t MINIMUN_RANDOM_NUMBER_100 = 100;
44 const int32_t MAXIMUN_RANDOM_NUMBER_999 = 999;
45
ToLower(const std::string & s)46 std::string PrintUtils::ToLower(const std::string &s)
47 {
48 std::string res = s;
49 std::transform(res.begin(), res.end(), res.begin(), tolower);
50 return res;
51 }
52
GetExtensionId(const std::string & globalId)53 std::string PrintUtils::GetExtensionId(const std::string &globalId)
54 {
55 auto pos = globalId.find(GLOBAL_ID_DELIMITER);
56 if (pos == std::string::npos) {
57 return "";
58 }
59 return globalId.substr(0, pos);
60 }
61
GetGlobalId(const std::string & extensionId,const std::string & localId)62 std::string PrintUtils::GetGlobalId(const std::string& extensionId, const std::string& localId)
63 {
64 return extensionId + GLOBAL_ID_DELIMITER + localId;
65 }
66
GetLocalId(const std::string & globalId,const std::string & extensionId)67 std::string PrintUtils::GetLocalId(const std::string& globalId, const std::string& extensionId)
68 {
69 auto pos = globalId.find(GLOBAL_ID_DELIMITER);
70 if (pos == std::string::npos) {
71 return "";
72 }
73
74 if (globalId.substr(0, pos) != extensionId) {
75 return "";
76 }
77 return globalId.substr(pos + 1);
78 }
79
EncodeExtensionCid(const std::string & extensionId,uint32_t callbackId)80 std::string PrintUtils::EncodeExtensionCid(const std::string &extensionId, uint32_t callbackId)
81 {
82 return extensionId + EXTENSION_CID_DELIMITER + std::to_string(callbackId);
83 }
84
DecodeExtensionCid(const std::string & cid,std::string & extensionId,uint32_t & callbackId)85 bool PrintUtils::DecodeExtensionCid(const std::string &cid, std::string &extensionId, uint32_t &callbackId)
86 {
87 auto pos = cid.find(EXTENSION_CID_DELIMITER);
88 if (pos == std::string::npos) {
89 return false;
90 }
91 extensionId = cid.substr(0, pos);
92 callbackId = static_cast<uint32_t>(atoi(cid.substr(pos + 1).c_str()));
93 return true;
94 }
95
GetTaskEventId(const std::string & taskId,const std::string & type)96 std::string PrintUtils::GetTaskEventId(const std::string &taskId, const std::string &type)
97 {
98 return type + TASK_EVENT_DELIMITER + taskId;
99 }
100
GetEventTypeWithToken(int64_t id,const std::string & type)101 std::string PrintUtils::GetEventTypeWithToken(int64_t id, const std::string &type)
102 {
103 std::string eventType = std::to_string(id) + TASK_EVENT_DELIMITER + type;
104 PRINT_HILOGD("eventType: %{public}s", eventType.c_str());
105 return eventType;
106 }
107
GetEventType(const std::string & type)108 std::string PrintUtils::GetEventType(const std::string &type)
109 {
110 auto pos = type.find(TASK_EVENT_DELIMITER);
111 if (pos == std::string::npos || pos + 1 >= type.length()) {
112 return "";
113 }
114 std::string eventType = type.substr(pos + 1);
115 PRINT_HILOGD("eventType: %{public}s", eventType.c_str());
116 return eventType;
117 }
118
OpenFile(const std::string & filePath)119 int32_t PrintUtils::OpenFile(const std::string &filePath)
120 {
121 if (filePath.find("content://") == 0) {
122 return DEFAULT_FD;
123 }
124 if (!IsPathValid(filePath)) {
125 return PRINT_INVALID_ID;
126 }
127 int32_t fd = open(filePath.c_str(), O_RDONLY);
128 PRINT_HILOGD("fd: %{public}d", fd);
129 if (fd < 0) {
130 PRINT_HILOGE("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
131 close(fd);
132 return PRINT_INVALID_ID;
133 }
134 return fd;
135 }
136
IsPathValid(const std::string & filePath)137 bool PrintUtils::IsPathValid(const std::string &filePath)
138 {
139 auto path = filePath.substr(0, filePath.rfind('/'));
140 char resolvedPath[PATH_MAX] = { 0 };
141 if (path.length() >= PATH_MAX || realpath(path.c_str(), resolvedPath) == nullptr ||
142 strncmp(resolvedPath, path.c_str(), path.length()) != 0) {
143 PRINT_HILOGE("invalid file path!");
144 return false;
145 }
146 return true;
147 }
148
GetIdFromFdPath(const std::string & fdPath)149 uint32_t PrintUtils::GetIdFromFdPath(const std::string &fdPath)
150 {
151 std::string fd_str = fdPath.substr(fdPath.rfind('/') + 1, fdPath.length());
152 std::stringstream getStrStream(fd_str);
153 uint32_t fd;
154 if (!(getStrStream >> fd)) {
155 PRINT_HILOGD("failed to convert to uint32");
156 }
157 return fd;
158 }
159
GetJobStateChar(const uint32_t state)160 std::string PrintUtils::GetJobStateChar(const uint32_t state)
161 {
162 if (jobStateMap_.size() == 0) {
163 jobStateMap_[PRINT_JOB_PREPARED] = "PRINT_JOB_PREPARED";
164 jobStateMap_[PRINT_JOB_QUEUED] = "PRINT_JOB_QUEUED";
165 jobStateMap_[PRINT_JOB_RUNNING] = "PRINT_JOB_RUNNING";
166 jobStateMap_[PRINT_JOB_BLOCKED] = "PRINT_JOB_BLOCKED";
167 jobStateMap_[PRINT_JOB_COMPLETED] = "PRINT_JOB_COMPLETED";
168 jobStateMap_[PRINT_JOB_CREATE_FILE_COMPLETED] = "PRINT_JOB_CREATE_FILE_COMPLETED";
169 jobStateMap_[PRINT_JOB_UNKNOWN] = "PRINT_JOB_UNKNOWN";
170 }
171 auto it = jobStateMap_.find(state);
172 if (it != jobStateMap_.end()) {
173 return it -> second;
174 }
175 return "PRINT_JOB_UNKNOWN";
176 }
177
BuildAdapterParam(const std::shared_ptr<AdapterParam> & adapterParam,AAFwk::Want & want)178 void PrintUtils::BuildAdapterParam(const std::shared_ptr<AdapterParam> &adapterParam, AAFwk::Want &want)
179 {
180 want.SetParam(LAUNCH_PARAMETER_DOCUMENT_NAME, adapterParam->documentName);
181 if (adapterParam->isCheckFdList) {
182 std::string defaultAttribute = "";
183 want.SetParam(LAUNCH_PARAMETER_PRINT_ATTRIBUTE, defaultAttribute);
184 return;
185 }
186 BuildPrintAttributesParam(adapterParam, want);
187 }
188
BuildPrintAttributesParam(const std::shared_ptr<AdapterParam> & adapterParam,AAFwk::Want & want)189 void PrintUtils::BuildPrintAttributesParam(const std::shared_ptr<AdapterParam> &adapterParam, AAFwk::Want &want)
190 {
191 json attrJson;
192 PrintAttributes attrParam = adapterParam->printAttributes;
193 if (attrParam.HasCopyNumber()) {
194 attrJson["copyNumber"] = attrParam.GetCopyNumber();
195 }
196 if (attrParam.HasSequential()) {
197 attrJson["isSequential"] = attrParam.GetIsSequential();
198 }
199 if (attrParam.HasLandscape()) {
200 attrJson["isLandscape"] = attrParam.GetIsLandscape();
201 }
202 if (attrParam.HasDirectionMode()) {
203 attrJson["directionMode"] = attrParam.GetDirectionMode();
204 }
205 if (attrParam.HasColorMode()) {
206 attrJson["colorMode"] = attrParam.GetColorMode();
207 }
208 if (attrParam.HasDuplexMode()) {
209 attrJson["duplexMode"] = attrParam.GetDuplexMode();
210 }
211 ParseAttributesObjectParamForJson(attrParam, attrJson);
212 if (attrParam.HasOption()) {
213 attrJson["options"] = attrParam.GetOption();
214 }
215 want.SetParam(LAUNCH_PARAMETER_PRINT_ATTRIBUTE, attrJson.dump());
216 PRINT_HILOGD("CallSpooler set printAttributes: %{public}s", attrJson.dump().c_str());
217 }
218
ParseAttributesObjectParamForJson(const PrintAttributes & attrParam,nlohmann::json & attrJson)219 void PrintUtils::ParseAttributesObjectParamForJson(const PrintAttributes &attrParam, nlohmann::json &attrJson)
220 {
221 if (attrParam.HasPageRange()) {
222 json pageRangeJson;
223 PrintRange printRangeAttr;
224 attrParam.GetPageRange(printRangeAttr);
225 if (printRangeAttr.HasStartPage()) {
226 pageRangeJson["startPage"] = printRangeAttr.GetStartPage();
227 }
228 if (printRangeAttr.HasEndPage()) {
229 pageRangeJson["endPage"] = printRangeAttr.GetEndPage();
230 }
231 if (printRangeAttr.HasPages()) {
232 std::vector<uint32_t> pages;
233 printRangeAttr.GetPages(pages);
234 pageRangeJson["pages"] = pages;
235 }
236 attrJson["pageRange"] = pageRangeJson;
237 }
238 if (attrParam.HasPageSize()) {
239 json pageSizeJson;
240 PrintPageSize pageSizeAttr;
241 attrParam.GetPageSize(pageSizeAttr);
242 pageSizeJson["id"] = pageSizeAttr.GetId();
243 pageSizeJson["name"] = pageSizeAttr.GetName();
244 pageSizeJson["width"] = pageSizeAttr.GetWidth();
245 pageSizeJson["height"] = pageSizeAttr.GetHeight();
246 attrJson["pageSize"] = pageSizeJson;
247 }
248 if (attrParam.HasMargin()) {
249 json marginJson;
250 PrintMargin marginAttr;
251 attrParam.GetMargin(marginAttr);
252 if (marginAttr.HasTop()) {
253 marginJson["top"] = marginAttr.GetTop();
254 }
255 if (marginAttr.HasBottom()) {
256 marginJson["bottom"] = marginAttr.GetBottom();
257 }
258 if (marginAttr.HasLeft()) {
259 marginJson["left"] = marginAttr.GetLeft();
260 }
261 if (marginAttr.HasRight()) {
262 marginJson["right"] = marginAttr.GetRight();
263 }
264 attrJson["margin"] = marginJson;
265 }
266 }
267
GetBundleNameForUid(const int uid)268 std::string PrintUtils::GetBundleNameForUid(const int uid)
269 {
270 OHOS::AppExecFwk::BundleMgrClient bmsClient;
271 std::string bundleName = "";
272 auto ret = bmsClient.GetNameForUid(uid, bundleName);
273 if (ret != OHOS::ERR_OK || bundleName.empty()) {
274 PRINT_HILOGE("get bundleName failed.");
275 }
276 PRINT_HILOGI("bundleName: %{public}s", bundleName.c_str());
277 return bundleName;
278 }
279
GetPrintJobId()280 std::string PrintUtils::GetPrintJobId()
281 {
282 std::lock_guard<std::mutex> autoLock(instanceLock_);
283 auto nowTime = std::chrono::system_clock::now();
284 auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime.time_since_epoch()).count();
285 std::stringstream ss;
286 ss << timestamp;
287
288 std::random_device rd;
289 std::mt19937 gen((unsigned int)time(NULL));
290 std::uniform_int_distribution<> dis(MINIMUN_RANDOM_NUMBER_100, MAXIMUN_RANDOM_NUMBER_999);
291 int32_t randomNumber = dis(gen);
292 std::string jobId = ss.str() + "_" + std::to_string(randomNumber);
293 PRINT_HILOGI("jobId: %{public}s", jobId.c_str());
294 return jobId;
295 }
296 } // namespace OHOS::Print
297