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     return lastUsedPrinterId_;
151 }
152 
SetDefaultPrinter(const std::string &printerId, uint32_t type)153 int32_t PrintUserData::SetDefaultPrinter(const std::string &printerId, uint32_t type)
154 {
155     PRINT_HILOGI("begin SetDefaultPrinter");
156     PRINT_HILOGI("printerId: %{public}s", printerId.c_str());
157     PRINT_HILOGI("type: %{public}d", type);
158     if (type == DEFAULT_PRINTER_TYPE_SETTED_BY_USER) {
159         defaultPrinterId_ = printerId;
160         useLastUsedPrinterForDefault_ = false;
161     } else if (type == DEFAULT_PRINTER_TYPE_LAST_USED_PRINTER || type == DELETE_DEFAULT_PRINTER) {
162         defaultPrinterId_ = lastUsedPrinterId_;
163         useLastUsedPrinterForDefault_ = true;
164     } else if (type == DELETE_LAST_USED_PRINTER) {
165         defaultPrinterId_ = lastUsedPrinterId_;
166     }
167     PRINT_HILOGI("defaultPrinterId_: %{public}s", defaultPrinterId_.c_str());
168     if (!SetUserDataToFile()) {
169         PRINT_HILOGE("SetUserDataToFile failed.");
170         return E_PRINT_SERVER_FAILURE;
171     }
172 
173     return E_PRINT_NONE;
174 }
175 
GetDefaultPrinter()176 std::string PrintUserData::GetDefaultPrinter()
177 {
178     return defaultPrinterId_;
179 }
180 
CheckIfUseLastUsedPrinterForDefault()181 bool PrintUserData::CheckIfUseLastUsedPrinterForDefault()
182 {
183     PRINT_HILOGI("useLastUsedPrinterForDefault_: %{public}d", useLastUsedPrinterForDefault_);
184     return useLastUsedPrinterForDefault_;
185 }
186 
DeletePrinter(const std::string &printerId)187 void PrintUserData::DeletePrinter(const std::string &printerId)
188 {
189     DeletePrinterFromUsedPrinterList(printerId);
190     if (!strcmp(lastUsedPrinterId_.c_str(), printerId.c_str())) {
191         if (usedPrinterList_.size()) {
192             auto it = usedPrinterList_.begin();
193             lastUsedPrinterId_ = *it;
194             PRINT_HILOGI(
195                 "change last used printer for delete printer, printerId: %{public}s", lastUsedPrinterId_.c_str());
196         } else {
197             lastUsedPrinterId_ = "";
198             PRINT_HILOGW("last used printer is null");
199         }
200     }
201     if (!SetUserDataToFile()) {
202         PRINT_HILOGE("SetUserDataToFile failed.");
203         return;
204     }
205 }
206 
DeletePrinterFromUsedPrinterList(const std::string &printerId)207 void PrintUserData::DeletePrinterFromUsedPrinterList(const std::string &printerId)
208 {
209     std::lock_guard<std::recursive_mutex> lock(userDataMutex_);
210     for (auto it = usedPrinterList_.begin(); it != usedPrinterList_.end(); ++it) {
211         std::string id = *it;
212         PRINT_HILOGI("printerId in usedPrinterList_: %{public}s", id.c_str());
213         if (!strcmp(id.c_str(), printerId.c_str())) {
214             PRINT_HILOGI("find printerId in used printer list.");
215             usedPrinterList_.erase(it);
216             break;
217         }
218     }
219 }
220 
ParseUserData()221 void PrintUserData::ParseUserData()
222 {
223     std::string fileData = "";
224     if (!GetFileData(fileData)) {
225         PRINT_HILOGW("get file data failed");
226         return;
227     }
228     nlohmann::json jsonObject;
229     if (CheckFileData(fileData, jsonObject)) {
230         ParseUserDataFromJson(jsonObject);
231     }
232 }
233 
ParseUserDataFromJson(nlohmann::json &jsonObject)234 void PrintUserData::ParseUserDataFromJson(nlohmann::json &jsonObject)
235 {
236     if (!jsonObject.contains("print_user_data")) {
237         PRINT_HILOGW("can not find print_user_data");
238         return;
239     }
240     PRINT_HILOGI("userId_: %{public}d", userId_);
241     nlohmann::json userDataList = jsonObject["print_user_data"];
242     if (!userDataList.contains(std::to_string(userId_)) || !userDataList[std::to_string(userId_)].is_object()) {
243         PRINT_HILOGW("can not find current userId");
244         SetUserDataToFile();
245     }
246     nlohmann::json userData = userDataList[std::to_string(userId_)];
247     if (!userData.contains("defaultPrinter") || !userData["defaultPrinter"].is_string()) {
248         PRINT_HILOGW("can not find defaultPrinter");
249         return;
250     }
251     defaultPrinterId_ = userData["defaultPrinter"];
252     if (!userData.contains("lastUsedPrinter") || !userData["lastUsedPrinter"].is_string()) {
253         PRINT_HILOGW("can not find lastUsedPrinter");
254         return;
255     }
256     lastUsedPrinterId_ = userData["lastUsedPrinter"];
257     if (!userData.contains("useLastUsedPrinterForDefault") || !userData["useLastUsedPrinterForDefault"].is_boolean()) {
258         PRINT_HILOGW("can not find useLastUsedPrinterForDefault");
259         return;
260     }
261     useLastUsedPrinterForDefault_ = userData["useLastUsedPrinterForDefault"].get<bool>();
262     if (!userData.contains("usedPrinterList") || !userData["usedPrinterList"].is_array()) {
263         PRINT_HILOGW("can not find usedPrinterList");
264         return;
265     }
266     if (!ConvertJsonToUsedPrinterList(userData)) {
267         PRINT_HILOGW("convert json to usedPrinterList failed");
268         return;
269     }
270     PRINT_HILOGI(
271         "defaultPrinterId_: %{public}s, lastUsedPrinterId_: %{public}s, useLastUsedPrinterForDefault_: %{public}d",
272         defaultPrinterId_.c_str(),
273         lastUsedPrinterId_.c_str(),
274         useLastUsedPrinterForDefault_);
275 }
276 
ConvertJsonToUsedPrinterList(nlohmann::json &userData)277 bool PrintUserData::ConvertJsonToUsedPrinterList(nlohmann::json &userData)
278 {
279     nlohmann::json usedPrinterListJson = userData["usedPrinterList"];
280     for (auto &item : usedPrinterListJson.items()) {
281         if (!item.value().is_string()) {
282             PRINT_HILOGW("usedPrinterListJson item is not string");
283             return false;
284         }
285         nlohmann::json printerIdJson = item.value();
286         usedPrinterList_.push_back(printerIdJson.get<std::string>());
287     }
288     uint32_t size = usedPrinterList_.size();
289     PRINT_HILOGI("usedPrinterList_ size: %{public}d", size);
290     for (auto it = usedPrinterList_.begin(); it != usedPrinterList_.end(); ++it) {
291         PRINT_HILOGI("printerId in usedPrinterList_: %{public}s", it->c_str());
292     }
293     return true;
294 }
295 
ConvertUsedPrinterListToJson(nlohmann::json &usedPrinterListJson)296 void PrintUserData::ConvertUsedPrinterListToJson(nlohmann::json &usedPrinterListJson)
297 {
298     for (auto iter = usedPrinterList_.begin(); iter != usedPrinterList_.end(); ++iter) {
299         usedPrinterListJson.push_back(*iter);
300     }
301 }
302 
GetFileData(std::string &fileData)303 bool PrintUserData::GetFileData(std::string &fileData)
304 {
305     PRINT_HILOGI("begin GetFileData");
306     std::string userDataFilePath = PRINTER_SERVICE_FILE_PATH + "/" + PRINT_USER_DATA_FILE;
307     std::ifstream ifs(userDataFilePath.c_str(), std::ios::in | std::ios::binary);
308     if (!ifs.is_open()) {
309         PRINT_HILOGW("open printer list file fail");
310         char realPidFile[PATH_MAX] = {};
311         if (realpath(PRINTER_SERVICE_FILE_PATH.c_str(), realPidFile) == nullptr) {
312             PRINT_HILOGE("The realPidFile is null, errno:%{public}s", std::to_string(errno).c_str());
313             return E_PRINT_SERVER_FAILURE;
314         }
315         int32_t fd = open(userDataFilePath.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
316         PRINT_HILOGI("create file fd: %{public}d", fd);
317         if (fd < 0) {
318             PRINT_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
319             return false;
320         }
321         nlohmann::json userDataJson = nlohmann::json::object();
322         nlohmann::json jsonObject;
323         jsonObject["version"] = PRINT_USER_DATA_VERSION;
324         jsonObject["print_user_data"] = userDataJson;
325         fileData = jsonObject.dump();
326         size_t jsonLength = fileData.length();
327         auto writeLength = write(fd, fileData.c_str(), jsonLength);
328         close(fd);
329         if (writeLength < 0 && (size_t)writeLength != jsonLength) {
330             return false;
331         }
332     } else {
333         fileData.assign((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
334         ifs.close();
335     }
336     return true;
337 }
338 
SetUserDataToFile()339 bool PrintUserData::SetUserDataToFile()
340 {
341     PRINT_HILOGI("begin SetUserDataToFile");
342     std::string fileData = "";
343     if (!GetFileData(fileData)) {
344         PRINT_HILOGW("get file data failed");
345         return false;
346     }
347     nlohmann::json jsonObject;
348     if (CheckFileData(fileData, jsonObject)) {
349         PRINT_HILOGI("userId_: %{public}d", userId_);
350         nlohmann::json userData = nlohmann::json::object();
351         userData["defaultPrinter"] = defaultPrinterId_;
352         userData["lastUsedPrinter"] = lastUsedPrinterId_;
353         userData["useLastUsedPrinterForDefault"] = useLastUsedPrinterForDefault_;
354         nlohmann::json usedPrinterListJson = nlohmann::json::array();
355         ConvertUsedPrinterListToJson(usedPrinterListJson);
356         userData["usedPrinterList"] = usedPrinterListJson;
357         jsonObject["print_user_data"][std::to_string(userId_)] = userData;
358         std::string temp = jsonObject.dump();
359         PRINT_HILOGI("json temp: %{public}s", temp.c_str());
360         char realPidFile[PATH_MAX] = {};
361         std::string userDataFilePath = PRINTER_SERVICE_FILE_PATH + "/" + PRINT_USER_DATA_FILE;
362         if (realpath(PRINTER_SERVICE_FILE_PATH.c_str(), realPidFile) == nullptr) {
363             PRINT_HILOGE("The realPidFile is null, errno:%{public}s", std::to_string(errno).c_str());
364             return E_PRINT_SERVER_FAILURE;
365         }
366         int32_t fd = open(userDataFilePath.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
367         PRINT_HILOGI("SetUserDataToFile fd: %{public}d", fd);
368         if (fd < 0) {
369             PRINT_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
370             return false;
371         }
372         std::string jsonString = jsonObject.dump();
373         size_t jsonLength = jsonString.length();
374         auto writeLength = write(fd, jsonString.c_str(), jsonLength);
375         close(fd);
376         PRINT_HILOGI("SetUserDataToFile finished");
377         if (writeLength < 0) {
378             return false;
379         }
380         return (size_t)writeLength == jsonLength;
381     }
382     return true;
383 }
384 
CheckFileData(std::string &fileData, nlohmann::json &jsonObject)385 bool PrintUserData::CheckFileData(std::string &fileData, nlohmann::json &jsonObject)
386 {
387     if (!nlohmann::json::accept(fileData)) {
388         PRINT_HILOGW("json accept fail");
389         return false;
390     }
391     jsonObject = nlohmann::json::parse(fileData);
392     if (!jsonObject.contains("version") || !jsonObject["version"].is_string()) {
393         PRINT_HILOGW("can not find version");
394         return false;
395     }
396     std::string version = jsonObject["version"].get<std::string>();
397     PRINT_HILOGI("json version: %{public}s", version.c_str());
398     if (version != PRINT_USER_DATA_VERSION || !jsonObject.contains("print_user_data")) {
399         PRINT_HILOGW("can not find print_user_data");
400         return false;
401     }
402     return true;
403 }
404 }  // namespace Print
405 }  // namespace OHOS