1 /*
2  * Copyright (c) 2024 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 <fcntl.h>
17 #include <unistd.h>
18 #include <iostream>
19 #include <fstream>
20 #include <streambuf>
21 #include "scan_log.h"
22 #include "scan_usb_manager.h"
23 #include "scan_system_data.h"
24 
25 namespace {
26 const std::string SCANNER_LIST_FILE = "/data/service/el2/public/print_service/sane/tmp/scanner_list.json";
27 const std::string SCANNER_LIST_VERSION = "v1";
28 }  // namespace
29 
30 namespace OHOS {
31 namespace Scan {
32 std::map<std::string, std::string> ScanSystemData::usbSnToPortMap_;
CheckJsonObjectValue(const nlohmann::json& object)33 bool ScanSystemData::CheckJsonObjectValue(const nlohmann::json& object)
34 {
35     const std::vector<std::string> keyList = {"deviceId", "manufacturer", "model", "deviceType",
36         "discoverMode", "serialNumber", "deviceName"};
37     for (auto key : keyList) {
38         if (!object.contains(key) || !object[key].is_string()) {
39             SCAN_HILOGW("can not find %{public}s", key.c_str());
40             return false;
41         }
42     }
43     return true;
44 }
45 
ParseScannerListJsonV1(nlohmann::json& jsonObject)46 bool ScanSystemData::ParseScannerListJsonV1(nlohmann::json& jsonObject)
47 {
48     if (!jsonObject.contains("scaner_list") || !jsonObject["scaner_list"].is_array()) {
49         SCAN_HILOGW("can not find scaner_list");
50         return false;
51     }
52     for (auto &element : jsonObject["scaner_list"].items()) {
53         nlohmann::json object = element.value();
54         if (!CheckJsonObjectValue(object)) {
55             continue;
56         }
57         ScanDeviceInfo scanDeviceInfo;
58         scanDeviceInfo.deviceId = object["deviceId"];
59         scanDeviceInfo.manufacturer = object["manufacturer"];
60         scanDeviceInfo.model = object["model"];
61         scanDeviceInfo.deviceType = object["deviceType"];
62         scanDeviceInfo.discoverMode = object["discoverMode"];
63         scanDeviceInfo.serialNumber = object["serialNumber"];
64         scanDeviceInfo.deviceName = object["deviceName"];
65         std::string uniqueId = scanDeviceInfo.discoverMode + scanDeviceInfo.serialNumber;
66         InsertScannerInfo(uniqueId, scanDeviceInfo);
67     }
68     RefreshUsbDeviceId();
69     return true;
70 }
71 
Init()72 bool ScanSystemData::Init()
73 {
74     addedScannerMap_.clear();
75     std::ifstream ifs(SCANNER_LIST_FILE.c_str(), std::ios::in | std::ios::binary);
76     if (!ifs.is_open()) {
77         SCAN_HILOGW("open scanner list file fail");
78         return false;
79     }
80     std::string fileData((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
81     ifs.close();
82     if (!nlohmann::json::accept(fileData)) {
83         SCAN_HILOGW("json accept fail");
84         return false;
85     }
86     nlohmann::json jsonObject = nlohmann::json::parse(fileData);
87     if (!jsonObject.contains("version") || !jsonObject["version"].is_string()) {
88         SCAN_HILOGW("can not find version");
89         return false;
90     }
91     std::string version = jsonObject["version"].get<std::string>();
92     SCAN_HILOGI("json version: %{public}s", version.c_str());
93     if (version == SCANNER_LIST_VERSION) {
94         return ParseScannerListJsonV1(jsonObject);
95     }
96     return false;
97 }
98 
RefreshUsbDeviceId()99 void ScanSystemData::RefreshUsbDeviceId()
100 {
101     ScanUsbManager::GetInstance()->RefreshUsbDevicePort();
102     if (usbSnToPortMap_.empty()) {
103         SCAN_HILOGW("Failed to refresh the USB device.");
104         return;
105     }
106     for (auto &scanDevIt : addedScannerMap_) {
107         std::string discoverMode = scanDevIt.second->discoverMode;
108         if (discoverMode == "TCP") {
109             continue;
110         }
111         std::string serialNumber = scanDevIt.second->serialNumber;
112         auto it = usbSnToPortMap_.find(serialNumber);
113         if (it == usbSnToPortMap_.end()) {
114             continue;
115         }
116         std::string oldDeviceId = scanDevIt.second->deviceId;
117         std::string usbPort = it->second;
118         if (oldDeviceId.find_last_of(":") == std::string::npos ||
119             oldDeviceId.find_last_of(":") < USB_DEVICEID_FIRSTID_LEN_3 ||
120             usbPort.find("_") == std::string::npos) {
121             SCAN_HILOGE("oldDeviceId or usbPort string format fail");
122             return;
123         }
124         std::string newDeviceId = GetNewDeviceId(oldDeviceId, usbPort);
125         scanDevIt.second->deviceId = newDeviceId;
126     }
127     if (!SaveScannerMap()) {
128         SCAN_HILOGW("Failed to save the JSON file.");
129     }
130 }
131 
GetNewDeviceId(std::string oldDeviceId, std::string usbDevicePort)132 std::string ScanSystemData::GetNewDeviceId(std::string oldDeviceId, std::string usbDevicePort)
133 {
134     std::string deviceIdHead = oldDeviceId.substr(0, oldDeviceId.find_last_of(":") - USB_DEVICEID_FIRSTID_LEN_3);
135     std::string firstPort = usbDevicePort.substr(0, usbDevicePort.find("-"));
136     std::string secondPort = usbDevicePort.substr(usbDevicePort.find("-") + 1, usbDevicePort.size() - 1);
137     SCAN_HILOGI("firstPort = %{public}s, secondPort = %{public}s.",
138                 firstPort.c_str(), secondPort.c_str());
139     FormatUsbPort(firstPort);
140     FormatUsbPort(secondPort);
141     return deviceIdHead + firstPort + ":" + secondPort;
142 }
143 
FormatUsbPort(std::string &port)144 void ScanSystemData::FormatUsbPort(std::string &port)
145 {
146     port.insert(0, USB_DEVICEID_FIRSTID_LEN_3 - port.size(), '0');
147 }
148 
UpdateScannerIdByUsbDevicePort(const std::string &uniqueId, const std::string &usbDevicePort)149 bool ScanSystemData::UpdateScannerIdByUsbDevicePort(const std::string &uniqueId, const std::string &usbDevicePort)
150 {
151     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
152     auto iter = addedScannerMap_.find(uniqueId);
153     if (iter != addedScannerMap_.end()) {
154         std::string oldDeviceId = iter->second->deviceId;
155         if (oldDeviceId.find_last_of(":") == std::string::npos ||
156             oldDeviceId.find_last_of(":") < USB_DEVICEID_FIRSTID_LEN_3 ||
157             usbDevicePort.find("_") == std::string::npos) {
158             SCAN_HILOGE("oldDeviceId or usbPort string format fail");
159             return false;
160         }
161         std::string newDeviceId = GetNewDeviceId(oldDeviceId, usbDevicePort);
162         iter->second->deviceId = newDeviceId;
163     } else {
164         SCAN_HILOGE("ScanSystemData UpdateScannerIdByUsbDevicePort fail");
165         return false;
166     }
167     return true;
168 }
169 
InsertScannerInfo(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)170 void ScanSystemData::InsertScannerInfo(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)
171 {
172     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
173     auto iter = addedScannerMap_.find(uniqueId);
174     if (iter == addedScannerMap_.end() || iter->second == nullptr) {
175         SCAN_HILOGI("insert new scanner");
176         addedScannerMap_[uniqueId] = std::make_shared<ScanDeviceInfo>(scannerInfo);
177     } else {
178         SCAN_HILOGI("update exist scanner");
179         iter->second->deviceId = scannerInfo.deviceId;
180         iter->second->manufacturer = scannerInfo.manufacturer;
181         iter->second->model = scannerInfo.model;
182         iter->second->deviceType = scannerInfo.deviceType;
183         iter->second->serialNumber = scannerInfo.serialNumber;
184         iter->second->deviceName = scannerInfo.deviceName;
185     }
186 }
187 
DeleteScannerInfo(const std::string &uniqueId)188 bool ScanSystemData::DeleteScannerInfo(const std::string &uniqueId)
189 {
190     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
191     auto iter = addedScannerMap_.find(uniqueId);
192     if (iter != addedScannerMap_.end()) {
193         addedScannerMap_.erase(uniqueId);
194     } else {
195         SCAN_HILOGE("ScanSystemData delete connected scanner fail");
196         return false;
197     }
198     return true;
199 }
200 
UpdateScannerNameByUniqueId(const std::string &uniqueId, const std::string &deviceName)201 bool ScanSystemData::UpdateScannerNameByUniqueId(const std::string &uniqueId, const std::string &deviceName)
202 {
203     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
204     auto iter = addedScannerMap_.find(uniqueId);
205     if (iter != addedScannerMap_.end() && iter->second != nullptr) {
206         iter->second->deviceName = deviceName;
207     } else {
208         SCAN_HILOGE("ScanSystemData UpdateScannerNameByUniqueId fail");
209         return false;
210     }
211     return true;
212 }
213 
UpdateScannerInfoByUniqueId(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)214 bool ScanSystemData::UpdateScannerInfoByUniqueId(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)
215 {
216     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
217     auto iter = addedScannerMap_.find(uniqueId);
218     if (iter != addedScannerMap_.end()) {
219         iter->second->deviceId = scannerInfo.deviceId;
220         iter->second->model = scannerInfo.model;
221         iter->second->deviceType = scannerInfo.deviceType;
222         iter->second->serialNumber = scannerInfo.serialNumber;
223         iter->second->deviceName = scannerInfo.deviceName;
224         return true;
225     }
226     SCAN_HILOGE("ScanSystemData UpdateScannerInfoByUniqueId not found scannerInfo");
227     return false;
228 }
229 
QueryScannerNameByUniqueId(const std::string &uniqueId, std::string &deviceName)230 bool ScanSystemData::QueryScannerNameByUniqueId(const std::string &uniqueId, std::string &deviceName)
231 {
232     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
233     auto iter = addedScannerMap_.find(uniqueId);
234     if (iter != addedScannerMap_.end()) {
235         deviceName = iter->second->deviceName;
236         return true;
237     }
238     SCAN_HILOGW("QueryScannerNameByUniqueId fail");
239     return false;
240 }
241 
QueryScannerInfoByUniqueId(const std::string &uniqueId, ScanDeviceInfo &scannerInfo)242 bool ScanSystemData::QueryScannerInfoByUniqueId(const std::string &uniqueId, ScanDeviceInfo &scannerInfo)
243 {
244     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
245     for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
246         auto info = iter->second;
247         if (info == nullptr) {
248             continue;
249         }
250         std::string iterUniqueId = info->discoverMode + info->serialNumber;
251         if (uniqueId == iterUniqueId) {
252             scannerInfo.deviceId = info->deviceId;
253             scannerInfo.manufacturer = info->manufacturer;
254             scannerInfo.model = info->model;
255             scannerInfo.deviceType = info->deviceType;
256             scannerInfo.discoverMode = info->discoverMode;
257             scannerInfo.serialNumber = info->serialNumber;
258             scannerInfo.deviceName = info->deviceName;
259             return true;
260         }
261     }
262     return false;
263 }
264 
GetAddedScannerInfoList(std::vector<ScanDeviceInfo> &infoList)265 void ScanSystemData::GetAddedScannerInfoList(std::vector<ScanDeviceInfo> &infoList)
266 {
267     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
268     for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
269         if (iter->second != nullptr) {
270             infoList.push_back(*(iter->second));
271         }
272     }
273 }
274 
SaveScannerMap()275 bool ScanSystemData::SaveScannerMap()
276 {
277     int32_t fd = open(SCANNER_LIST_FILE.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
278     SCAN_HILOGD("SaveScannerMap fd: %{public}d", fd);
279     if (fd < 0) {
280         SCAN_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
281         return false;
282     }
283     nlohmann::json scannerMapJson = nlohmann::json::array();
284     {
285         std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
286         for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
287             auto info = iter->second;
288             if (info == nullptr) {
289                 continue;
290             }
291             nlohmann::json scannerJson = nlohmann::json::object();
292             scannerJson["deviceId"] = info->deviceId;
293             scannerJson["manufacturer"] = info->manufacturer;
294             scannerJson["model"] = info->model;
295             scannerJson["deviceType"] = info->deviceType;
296             scannerJson["discoverMode"] = info->discoverMode;
297             scannerJson["serialNumber"] = info->serialNumber;
298             scannerJson["deviceName"] = info->deviceName;
299             scannerMapJson.push_back(scannerJson);
300         }
301     }
302     nlohmann::json jsonObject;
303     jsonObject["version"] = SCANNER_LIST_VERSION;
304     jsonObject["scaner_list"] = scannerMapJson;
305     std::string jsonString = jsonObject.dump();
306     size_t jsonLength = jsonString.length();
307     auto writeLength = write(fd, jsonString.c_str(), jsonLength);
308     close(fd);
309     fd = -1;
310     SCAN_HILOGI("SaveScannerMap finished");
311     if (writeLength < 0) {
312         return false;
313     }
314     return (size_t)writeLength == jsonLength;
315 }
316 
IsContainScanner(const std::string &uniqueId)317 bool ScanSystemData::IsContainScanner(const std::string &uniqueId)
318 {
319     if (addedScannerMap_.find(uniqueId) != addedScannerMap_.end()) {
320         SCAN_HILOGI("The map contains the scanner.");
321         return true;
322     } else {
323         SCAN_HILOGW("The scanner is not included in the map.");
324         return false;
325     }
326 }
327 }  // namespace Scan
328 }  // namespace OHOS