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