1 /*
2  * Copyright (c) 2023 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_user_data.h"
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <iostream>
20 #include <fstream>
21 #include <streambuf>
22 #include "nlohmann/json.hpp"
23 
24 #include "print_log.h"
25 #include "print_constant.h"
26 
27 namespace OHOS {
28 namespace Print {
29 
RegisterPrinterCallback(const std::string & type,const sptr<IPrintCallback> & listener)30 void PrintUserData::RegisterPrinterCallback(const std::string &type, const sptr<IPrintCallback> &listener)
31 {
32     registeredListeners_[type] = listener;
33 }
34 
UnregisterPrinterCallback(const std::string & type)35 void PrintUserData::UnregisterPrinterCallback(const std::string &type)
36 {
37     auto iter = registeredListeners_.find(type);
38     if (iter != registeredListeners_.end()) {
39         registeredListeners_.erase(iter);
40     }
41 }
42 
SendPrinterEvent(const std::string & type,int event,const PrinterInfo & info)43 void PrintUserData::SendPrinterEvent(const std::string &type, int event, const PrinterInfo &info)
44 {
45     auto iter = registeredListeners_.find(type);
46     if (iter != registeredListeners_.end() && iter->second != nullptr) {
47         iter->second->OnCallback(event, info);
48     }
49 }
50 
AddToPrintJobList(const std::string jobId,const std::shared_ptr<PrintJob> & printjob)51 void PrintUserData::AddToPrintJobList(const std::string jobId, const std::shared_ptr<PrintJob> &printjob)
52 {
53     printJobList_.insert(std::make_pair(jobId, printjob));
54 }
55 
UpdateQueuedJobList(const std::string & jobId,const std::shared_ptr<PrintJob> & printJob,std::string jobOrderId)56 void PrintUserData::UpdateQueuedJobList(
57     const std::string &jobId, const std::shared_ptr<PrintJob> &printJob, std::string jobOrderId)
58 {
59     if (jobOrderId == "0") {
60         jobOrderList_.clear();
61     }
62     auto jobIt = printJobList_.find(jobId);
63     if (jobIt == printJobList_.end()) {
64         PRINT_HILOGE("invalid job id");
65         return;
66     }
67     printJobList_.erase(jobIt);
68 
69     if (queuedJobList_.find(jobId) != queuedJobList_.end()) {
70         queuedJobList_[jobId] = printJob;
71         jobOrderList_[jobOrderId] = jobId;
72     } else {
73         queuedJobList_.insert(std::make_pair(jobId, printJob));
74         jobOrderList_.insert(std::make_pair(jobOrderId, jobId));
75     }
76 }
77 
QueryPrintJobById(std::string & printJobId,PrintJob & printJob)78 int32_t PrintUserData::QueryPrintJobById(std::string &printJobId, PrintJob &printJob)
79 {
80     if (printJobList_.empty()) {
81         PRINT_HILOGE("printJobList is empty!");
82         return E_PRINT_INVALID_PRINTJOB;
83     }
84     auto jobIt = printJobList_.find(printJobId);
85     if (jobIt == printJobList_.end()) {
86         PRINT_HILOGW("no print job exists");
87         return E_PRINT_INVALID_PRINTJOB;
88     } else {
89         if (jobIt->second != nullptr) {
90             printJob = *jobIt->second;
91         }
92     }
93     PRINT_HILOGI("QueryPrintJobById End.");
94     return E_PRINT_NONE;
95 }
96 
QueryAllPrintJob(std::vector<PrintJob> & printJobs)97 int32_t PrintUserData::QueryAllPrintJob(std::vector<PrintJob> &printJobs)
98 {
99     printJobs.clear();
100     for (auto iter : jobOrderList_) {
101         PRINT_HILOGI("QueryAllPrintJob queuedJobList_ jobOrderId: %{public}s, jobId: %{public}s",
102             iter.first.c_str(),
103             iter.second.c_str());
104         auto jobIt = queuedJobList_.find(iter.second);
105         if (jobIt == queuedJobList_.end()) {
106             PRINT_HILOGW("This job dose not exist.");
107             continue;
108         } else {
109             if (jobIt->second != nullptr) {
110                 printJobs.emplace_back(*jobIt->second);
111             }
112         }
113     }
114     PRINT_HILOGI("QueryAllPrintJob End.");
115     return E_PRINT_NONE;
116 }
117 
SetUserId(int32_t userId)118 void PrintUserData::SetUserId(int32_t userId)
119 {
120     userId_ = userId;
121 }
122 
SetLastUsedPrinter(const std::string & printerId)123 int32_t PrintUserData::SetLastUsedPrinter(const std::string &printerId)
124 {
125     PRINT_HILOGI("begin SetLastUsedPrinter, printerId: %{public}s", printerId.c_str());
126     if (printerId.empty()) {
127         PRINT_HILOGE("printerId is empty");
128         return E_PRINT_INVALID_PARAMETER;
129     }
130     std::lock_guard<std::recursive_mutex> lock(userDataMutex_);
131     lastUsedPrinterId_ = printerId;
132 
133     DeletePrinterFromUsedPrinterList(printerId);
134     usedPrinterList_.push_front(printerId);
135     PRINT_HILOGI("put printer at the head of the queue, printerId: %{public}s", usedPrinterList_.front().c_str());
136     if (useLastUsedPrinterForDefault_) {
137         defaultPrinterId_ = printerId;
138         PRINT_HILOGI("set the last used printer as the default printer");
139     }
140     if (!SetUserDataToFile()) {
141         PRINT_HILOGE("SetUserDataToFile failed.");
142         return E_PRINT_SERVER_FAILURE;
143     }
144 
145     return E_PRINT_NONE;
146 }
147 
GetLastUsedPrinter()148 std::string PrintUserData::GetLastUsedPrinter()
149 {
150     std::lock_guard<std::recursive_mutex> lock(userDataMutex_);
151     return lastUsedPrinterId_;
152 }
153 
SetDefaultPrinter(const std::string & printerId,uint32_t type)154 int32_t PrintUserData::SetDefaultPrinter(const std::string &printerId, uint32_t type)
155 {
156     std::lock_guard<std::recursive_mutex> lock(userDataMutex_);
157     PRINT_HILOGI("begin SetDefaultPrinter");
158     PRINT_HILOGI("printerId: %{public}s", printerId.c_str());
159     PRINT_HILOGI("type: %{public}d", type);
160     if (type == DEFAULT_PRINTER_TYPE_SETTED_BY_USER) {
161         defaultPrinterId_ = printerId;
162         useLastUsedPrinterForDefault_ = false;
163     } else if (type == DEFAULT_PRINTER_TYPE_LAST_USED_PRINTER || type == DELETE_DEFAULT_PRINTER) {
164         defaultPrinterId_ = lastUsedPrinterId_;
165         useLastUsedPrinterForDefault_ = true;
166     } else if (type == DELETE_LAST_USED_PRINTER) {
167         defaultPrinterId_ = lastUsedPrinterId_;
168     }
169     PRINT_HILOGI("defaultPrinterId_: %{public}s", defaultPrinterId_.c_str());
170     if (!SetUserDataToFile()) {
171         PRINT_HILOGE("SetUserDataToFile failed.");
172         return E_PRINT_SERVER_FAILURE;
173     }
174 
175     return E_PRINT_NONE;
176 }
177 
GetDefaultPrinter()178 std::string PrintUserData::GetDefaultPrinter()
179 {
180     return defaultPrinterId_;
181 }
182 
CheckIfUseLastUsedPrinterForDefault()183 bool PrintUserData::CheckIfUseLastUsedPrinterForDefault()
184 {
185     PRINT_HILOGI("useLastUsedPrinterForDefault_: %{public}d", useLastUsedPrinterForDefault_);
186     return useLastUsedPrinterForDefault_;
187 }
188 
DeletePrinter(const std::string & printerId)189 void PrintUserData::DeletePrinter(const std::string &printerId)
190 {
191     DeletePrinterFromUsedPrinterList(printerId);
192     if (!strcmp(lastUsedPrinterId_.c_str(), printerId.c_str())) {
193         std::lock_guard<std::recursive_mutex> lock(userDataMutex_);
194         if (usedPrinterList_.size()) {
195             auto it = usedPrinterList_.begin();
196             lastUsedPrinterId_ = *it;
197             PRINT_HILOGI(
198                 "change last used printer for delete printer, printerId: %{public}s", lastUsedPrinterId_.c_str());
199         } else {
200             lastUsedPrinterId_ = "";
201             PRINT_HILOGW("last used printer is null");
202         }
203     }
204     if (!SetUserDataToFile()) {
205         PRINT_HILOGE("SetUserDataToFile failed.");
206         return;
207     }
208 }
209 
DeletePrinterFromUsedPrinterList(const std::string & printerId)210 void PrintUserData::DeletePrinterFromUsedPrinterList(const std::string &printerId)
211 {
212     std::lock_guard<std::recursive_mutex> lock(userDataMutex_);
213     for (auto it = usedPrinterList_.begin(); it != usedPrinterList_.end(); ++it) {
214         std::string id = *it;
215         PRINT_HILOGI("printerId in usedPrinterList_: %{public}s", id.c_str());
216         if (!strcmp(id.c_str(), printerId.c_str())) {
217             PRINT_HILOGI("find printerId in used printer list.");
218             usedPrinterList_.erase(it);
219             break;
220         }
221     }
222 }
223 
ParseUserData()224 void PrintUserData::ParseUserData()
225 {
226     std::string fileData = "";
227     if (!GetFileData(fileData)) {
228         PRINT_HILOGW("get file data failed");
229         return;
230     }
231     nlohmann::json jsonObject;
232     if (CheckFileData(fileData, jsonObject)) {
233         ParseUserDataFromJson(jsonObject);
234     }
235 }
236 
ParseUserDataFromJson(nlohmann::json & jsonObject)237 void PrintUserData::ParseUserDataFromJson(nlohmann::json &jsonObject)
238 {
239     if (!jsonObject.contains("print_user_data")) {
240         PRINT_HILOGW("can not find print_user_data");
241         return;
242     }
243     PRINT_HILOGI("userId_: %{public}d", userId_);
244     nlohmann::json userDataList = jsonObject["print_user_data"];
245     if (!userDataList.contains(std::to_string(userId_)) || !userDataList[std::to_string(userId_)].is_object()) {
246         PRINT_HILOGW("can not find current userId");
247         SetUserDataToFile();
248     }
249     nlohmann::json userData = userDataList[std::to_string(userId_)];
250     if (!userData.contains("defaultPrinter") || !userData["defaultPrinter"].is_string()) {
251         PRINT_HILOGW("can not find defaultPrinter");
252         return;
253     }
254     defaultPrinterId_ = userData["defaultPrinter"];
255     if (!userData.contains("lastUsedPrinter") || !userData["lastUsedPrinter"].is_string()) {
256         PRINT_HILOGW("can not find lastUsedPrinter");
257         return;
258     }
259     lastUsedPrinterId_ = userData["lastUsedPrinter"];
260     if (!userData.contains("useLastUsedPrinterForDefault") || !userData["useLastUsedPrinterForDefault"].is_boolean()) {
261         PRINT_HILOGW("can not find useLastUsedPrinterForDefault");
262         return;
263     }
264     useLastUsedPrinterForDefault_ = userData["useLastUsedPrinterForDefault"].get<bool>();
265     if (!userData.contains("usedPrinterList") || !userData["usedPrinterList"].is_array()) {
266         PRINT_HILOGW("can not find usedPrinterList");
267         return;
268     }
269     if (!ConvertJsonToUsedPrinterList(userData)) {
270         PRINT_HILOGW("convert json to usedPrinterList failed");
271         return;
272     }
273     PRINT_HILOGI(
274         "defaultPrinterId_: %{public}s, lastUsedPrinterId_: %{public}s, useLastUsedPrinterForDefault_: %{public}d",
275         defaultPrinterId_.c_str(),
276         lastUsedPrinterId_.c_str(),
277         useLastUsedPrinterForDefault_);
278 }
279 
ConvertJsonToUsedPrinterList(nlohmann::json & userData)280 bool PrintUserData::ConvertJsonToUsedPrinterList(nlohmann::json &userData)
281 {
282     nlohmann::json usedPrinterListJson = userData["usedPrinterList"];
283     for (auto &item : usedPrinterListJson.items()) {
284         if (!item.value().is_string()) {
285             PRINT_HILOGW("usedPrinterListJson item is not string");
286             return false;
287         }
288         nlohmann::json printerIdJson = item.value();
289         usedPrinterList_.push_back(printerIdJson.get<std::string>());
290     }
291     uint32_t size = usedPrinterList_.size();
292     PRINT_HILOGI("usedPrinterList_ size: %{public}d", size);
293     for (auto it = usedPrinterList_.begin(); it != usedPrinterList_.end(); ++it) {
294         PRINT_HILOGI("printerId in usedPrinterList_: %{public}s", it->c_str());
295     }
296     return true;
297 }
298 
ConvertUsedPrinterListToJson(nlohmann::json & usedPrinterListJson)299 void PrintUserData::ConvertUsedPrinterListToJson(nlohmann::json &usedPrinterListJson)
300 {
301     for (auto iter = usedPrinterList_.begin(); iter != usedPrinterList_.end(); ++iter) {
302         usedPrinterListJson.push_back(*iter);
303     }
304 }
305 
GetFileData(std::string & fileData)306 bool PrintUserData::GetFileData(std::string &fileData)
307 {
308     PRINT_HILOGI("begin GetFileData");
309     std::string userDataFilePath = PRINTER_SERVICE_FILE_PATH + "/" + PRINT_USER_DATA_FILE;
310     std::ifstream ifs(userDataFilePath.c_str(), std::ios::in | std::ios::binary);
311     if (!ifs.is_open()) {
312         PRINT_HILOGW("open printer list file fail");
313         char realPidFile[PATH_MAX] = {};
314         if (realpath(PRINTER_SERVICE_FILE_PATH.c_str(), realPidFile) == nullptr) {
315             PRINT_HILOGE("The realPidFile is null, errno:%{public}s", std::to_string(errno).c_str());
316             return false;
317         }
318         int32_t fd = open(userDataFilePath.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
319         PRINT_HILOGI("create file fd: %{public}d", fd);
320         if (fd < 0) {
321             PRINT_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
322             return false;
323         }
324         nlohmann::json userDataJson = nlohmann::json::object();
325         nlohmann::json jsonObject;
326         jsonObject["version"] = PRINT_USER_DATA_VERSION;
327         jsonObject["print_user_data"] = userDataJson;
328         fileData = jsonObject.dump();
329         size_t jsonLength = fileData.length();
330         auto writeLength = write(fd, fileData.c_str(), jsonLength);
331         close(fd);
332         if (writeLength < 0 && (size_t)writeLength != jsonLength) {
333             return false;
334         }
335     } else {
336         fileData.assign((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
337         ifs.close();
338     }
339     return true;
340 }
341 
SetUserDataToFile()342 bool PrintUserData::SetUserDataToFile()
343 {
344     PRINT_HILOGI("begin SetUserDataToFile");
345     std::string fileData = "";
346     if (!GetFileData(fileData)) {
347         PRINT_HILOGW("get file data failed");
348         return false;
349     }
350     nlohmann::json jsonObject;
351     if (CheckFileData(fileData, jsonObject)) {
352         PRINT_HILOGI("userId_: %{public}d", userId_);
353         nlohmann::json userData = nlohmann::json::object();
354         userData["defaultPrinter"] = defaultPrinterId_;
355         userData["lastUsedPrinter"] = lastUsedPrinterId_;
356         userData["useLastUsedPrinterForDefault"] = useLastUsedPrinterForDefault_;
357         nlohmann::json usedPrinterListJson = nlohmann::json::array();
358         ConvertUsedPrinterListToJson(usedPrinterListJson);
359         userData["usedPrinterList"] = usedPrinterListJson;
360         jsonObject["print_user_data"][std::to_string(userId_)] = userData;
361         std::string temp = jsonObject.dump();
362         PRINT_HILOGI("json temp: %{public}s", temp.c_str());
363         char realPidFile[PATH_MAX] = {};
364         std::string userDataFilePath = PRINTER_SERVICE_FILE_PATH + "/" + PRINT_USER_DATA_FILE;
365         if (realpath(PRINTER_SERVICE_FILE_PATH.c_str(), realPidFile) == nullptr) {
366             PRINT_HILOGE("The realPidFile is null, errno:%{public}s", std::to_string(errno).c_str());
367             return false;
368         }
369         int32_t fd = open(userDataFilePath.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
370         PRINT_HILOGI("SetUserDataToFile fd: %{public}d", fd);
371         if (fd < 0) {
372             PRINT_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
373             return false;
374         }
375         std::string jsonString = jsonObject.dump();
376         size_t jsonLength = jsonString.length();
377         auto writeLength = write(fd, jsonString.c_str(), jsonLength);
378         close(fd);
379         PRINT_HILOGI("SetUserDataToFile finished");
380         if (writeLength < 0) {
381             return false;
382         }
383         return (size_t)writeLength == jsonLength;
384     }
385     return true;
386 }
387 
CheckFileData(std::string & fileData,nlohmann::json & jsonObject)388 bool PrintUserData::CheckFileData(std::string &fileData, nlohmann::json &jsonObject)
389 {
390     if (!nlohmann::json::accept(fileData)) {
391         PRINT_HILOGW("json accept fail");
392         return false;
393     }
394     jsonObject = nlohmann::json::parse(fileData);
395     if (!jsonObject.contains("version") || !jsonObject["version"].is_string()) {
396         PRINT_HILOGW("can not find version");
397         return false;
398     }
399     std::string version = jsonObject["version"].get<std::string>();
400     PRINT_HILOGI("json version: %{public}s", version.c_str());
401     if (version != PRINT_USER_DATA_VERSION || !jsonObject.contains("print_user_data")) {
402         PRINT_HILOGW("can not find print_user_data");
403         return false;
404     }
405     return true;
406 }
407 }  // namespace Print
408 }  // namespace OHOS