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_util.h"
24 #include "scan_system_data.h"
25 #include "scan_service_ability.h"
26 
27 namespace {
28 const std::string SCANNER_LIST_FILE = "/data/service/el2/public/print_service/sane/tmp/scanner_list.json";
29 const std::string SCANNER_LIST_VERSION = "v1";
30 }  // namespace
31 
32 namespace OHOS {
33 namespace Scan {
34 std::map<std::string, std::string> ScanSystemData::usbSnToPortMap_;
CheckJsonObjectValue(const nlohmann::json & object)35 bool ScanSystemData::CheckJsonObjectValue(const nlohmann::json& object)
36 {
37     const std::vector<std::string> keyList = {"deviceId", "manufacturer", "model", "deviceType",
38         "discoverMode", "serialNumber", "deviceName", "uniqueId"};
39     for (auto key : keyList) {
40         if (!object.contains(key) || !object[key].is_string()) {
41             SCAN_HILOGW("can not find %{public}s", key.c_str());
42             return false;
43         }
44     }
45     return true;
46 }
47 
ParseScannerListJsonV1(nlohmann::json & jsonObject)48 bool ScanSystemData::ParseScannerListJsonV1(nlohmann::json& jsonObject)
49 {
50     if (!jsonObject.contains("scaner_list") || !jsonObject["scaner_list"].is_array()) {
51         SCAN_HILOGW("can not find scaner_list");
52         return false;
53     }
54     for (auto &element : jsonObject["scaner_list"].items()) {
55         nlohmann::json object = element.value();
56         if (!CheckJsonObjectValue(object)) {
57             continue;
58         }
59         ScanDeviceInfo scanDeviceInfo;
60         scanDeviceInfo.deviceId = object["deviceId"];
61         scanDeviceInfo.manufacturer = object["manufacturer"];
62         scanDeviceInfo.model = object["model"];
63         scanDeviceInfo.deviceType = object["deviceType"];
64         scanDeviceInfo.discoverMode = object["discoverMode"];
65         scanDeviceInfo.serialNumber = object["serialNumber"];
66         scanDeviceInfo.deviceName = object["deviceName"];
67         scanDeviceInfo.uniqueId = object["uniqueId"];
68         scanDeviceInfo.uuid = object["uuid"];
69         std::string uniqueId = scanDeviceInfo.discoverMode + scanDeviceInfo.uniqueId;
70         InsertScannerInfo(uniqueId, scanDeviceInfo);
71     }
72     RefreshUsbDeviceId();
73     return true;
74 }
75 
Init()76 bool ScanSystemData::Init()
77 {
78     addedScannerMap_.clear();
79     std::ifstream ifs(SCANNER_LIST_FILE.c_str(), std::ios::in | std::ios::binary);
80     if (!ifs.is_open()) {
81         SCAN_HILOGW("open scanner list file fail");
82         return false;
83     }
84     std::string fileData((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
85     ifs.close();
86     if (!nlohmann::json::accept(fileData)) {
87         SCAN_HILOGW("json accept fail");
88         return false;
89     }
90     nlohmann::json jsonObject = nlohmann::json::parse(fileData);
91     if (!jsonObject.contains("version") || !jsonObject["version"].is_string()) {
92         SCAN_HILOGW("can not find version");
93         return false;
94     }
95     std::string version = jsonObject["version"].get<std::string>();
96     SCAN_HILOGI("json version: %{public}s", version.c_str());
97     if (version == SCANNER_LIST_VERSION) {
98         return ParseScannerListJsonV1(jsonObject);
99     }
100     return false;
101 }
102 
RefreshUsbDeviceId()103 void ScanSystemData::RefreshUsbDeviceId()
104 {
105     ScanUsbManager::GetInstance()->RefreshUsbDevicePort();
106     if (usbSnToPortMap_.empty()) {
107         SCAN_HILOGW("Failed to refresh the USB device.");
108         return;
109     }
110     for (auto &scanDevIt : addedScannerMap_) {
111         std::string discoverMode = scanDevIt.second->discoverMode;
112         if (discoverMode == "TCP") {
113             continue;
114         }
115         std::string serialNumber = scanDevIt.second->serialNumber;
116         auto it = usbSnToPortMap_.find(serialNumber);
117         if (it == usbSnToPortMap_.end()) {
118             continue;
119         }
120         std::string oldDeviceId = scanDevIt.second->deviceId;
121         std::string usbPort = it->second;
122         std::string newDeviceId = ReplaceDeviceIdUsbPort(oldDeviceId, usbPort);
123         if (newDeviceId == "" || newDeviceId == oldDeviceId) {
124             SCAN_HILOGD("cannot update usb deviceId.");
125             continue;
126         }
127         scanDevIt.second->deviceId = newDeviceId;
128         ScanDeviceInfoSync syncInfo;
129         syncInfo.deviceId = newDeviceId;
130         syncInfo.serialNumber = serialNumber;
131         syncInfo.oldDeviceId = oldDeviceId;
132         syncInfo.discoverMode = "USB";
133         auto saPtr = ScanServiceAbility::GetInstance();
134         if (saPtr == nullptr) {
135             SCAN_HILOGE("saPtr is a nullptr");
136             return;
137         }
138         saPtr->UpdateScannerId(syncInfo);
139     }
140     if (!SaveScannerMap()) {
141         SCAN_HILOGW("Failed to save the JSON file.");
142     }
143 }
144 
ReplaceDeviceIdUsbPort(const std::string & deviceId,const std::string & usbPort)145 std::string ScanSystemData::ReplaceDeviceIdUsbPort(const std::string& deviceId, const std::string& usbPort)
146 {
147     constexpr int32_t invalidPort = -1;
148     int32_t start = invalidPort;
149     int32_t end = invalidPort;
150     char dash;
151     std::istringstream(usbPort) >> start >> dash >> end;
152     if (start < 0 || end < 0 || dash != '-') {
153         SCAN_HILOGE("usbPort format is error");
154         return "";
155     }
156     std::ostringstream oss;
157     char zero = '0';
158     constexpr int32_t portWidth = 3;
159     oss << std::setw(portWidth) << std::setfill(zero) << start;
160     std::string formattedStart = oss.str();
161     oss.str("");
162     oss << std::setw(portWidth) << std::setfill(zero) << end;
163     std::string formattedEnd = oss.str();
164     size_t pos1 = deviceId.rfind(':');
165     if (pos1 == std::string::npos) {
166         SCAN_HILOGE("deviceId format is error");
167         return "";
168     }
169     size_t pos2 = deviceId.rfind(':', pos1 - 1);
170     if (pos2 == std::string::npos) {
171         SCAN_HILOGE("deviceId format is error");
172         return "";
173     }
174     std::string newDeviceId = deviceId.substr(0, pos2 + 1).append(formattedStart).append(":").append(formattedEnd);
175     SCAN_HILOGD("new deviceId = %{private}s", newDeviceId.c_str());
176     return newDeviceId;
177 }
178 
GetNewDeviceId(std::string oldDeviceId,std::string usbDevicePort)179 std::string ScanSystemData::GetNewDeviceId(std::string oldDeviceId, std::string usbDevicePort)
180 {
181     if (oldDeviceId.find_last_of(":") == std::string::npos ||
182         oldDeviceId.find_last_of(":") < USB_DEVICEID_FIRSTID_LEN_3 ||
183         oldDeviceId.find_last_of("-") == std::string::npos ||
184         oldDeviceId.find_last_of("-") < 1) {
185         return nullptr;
186     }
187     std::string deviceIdHead = oldDeviceId.substr(0, oldDeviceId.find_last_of(":") - USB_DEVICEID_FIRSTID_LEN_3);
188     std::string firstPort = usbDevicePort.substr(0, usbDevicePort.find("-"));
189     std::string secondPort = usbDevicePort.substr(usbDevicePort.find("-") + 1, usbDevicePort.size() - 1);
190     SCAN_HILOGI("firstPort = %{public}s, secondPort = %{public}s.",
191                 firstPort.c_str(), secondPort.c_str());
192     FormatUsbPort(firstPort);
193     FormatUsbPort(secondPort);
194     return deviceIdHead + firstPort + ":" + secondPort;
195 }
196 
FormatUsbPort(std::string & port)197 void ScanSystemData::FormatUsbPort(std::string &port)
198 {
199     port.insert(0, USB_DEVICEID_FIRSTID_LEN_3 - port.size(), '0');
200 }
201 
UpdateScannerIdByUsbDevicePort(const std::string & uniqueId,const std::string & usbDevicePort)202 bool ScanSystemData::UpdateScannerIdByUsbDevicePort(const std::string &uniqueId, const std::string &usbDevicePort)
203 {
204     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
205     auto iter = addedScannerMap_.find(uniqueId);
206     if (iter != addedScannerMap_.end() && iter->second != nullptr) {
207         std::string oldDeviceId = iter->second->deviceId;
208         std::string newDeviceId = ReplaceDeviceIdUsbPort(oldDeviceId, usbDevicePort);
209         SCAN_HILOGD("newDeviceId : %{private}s", newDeviceId.c_str());
210         if (newDeviceId == "" || newDeviceId == oldDeviceId) {
211             SCAN_HILOGD("cannot update usb deviceId.");
212             return false;
213         }
214         iter->second->deviceId = newDeviceId;
215     } else {
216         SCAN_HILOGE("ScanSystemData UpdateScannerIdByUsbDevicePort fail");
217         return false;
218     }
219     return true;
220 }
221 
InsertScannerInfo(const std::string & uniqueId,const ScanDeviceInfo & scannerInfo)222 void ScanSystemData::InsertScannerInfo(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)
223 {
224     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
225     auto iter = addedScannerMap_.find(uniqueId);
226     if (iter == addedScannerMap_.end() || iter->second == nullptr) {
227         SCAN_HILOGI("insert new scanner");
228         addedScannerMap_[uniqueId] = std::make_shared<ScanDeviceInfo>(scannerInfo);
229     } else {
230         SCAN_HILOGI("update exist scanner");
231         iter->second->deviceId = scannerInfo.deviceId;
232         iter->second->manufacturer = scannerInfo.manufacturer;
233         iter->second->model = scannerInfo.model;
234         iter->second->deviceType = scannerInfo.deviceType;
235         iter->second->serialNumber = scannerInfo.serialNumber;
236         iter->second->deviceName = scannerInfo.deviceName;
237         iter->second->uniqueId = scannerInfo.uniqueId;
238         iter->second->uuid = scannerInfo.uuid;
239     }
240 }
241 
DeleteScannerInfo(const std::string & uniqueId)242 bool ScanSystemData::DeleteScannerInfo(const std::string &uniqueId)
243 {
244     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
245     auto iter = addedScannerMap_.find(uniqueId);
246     if (iter != addedScannerMap_.end()) {
247         addedScannerMap_.erase(uniqueId);
248     } else {
249         SCAN_HILOGE("ScanSystemData delete connected scanner fail");
250         return false;
251     }
252     return true;
253 }
254 
UpdateScannerNameByUniqueId(const std::string & uniqueId,const std::string & deviceName)255 bool ScanSystemData::UpdateScannerNameByUniqueId(const std::string &uniqueId, const std::string &deviceName)
256 {
257     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
258     auto iter = addedScannerMap_.find(uniqueId);
259     if (iter != addedScannerMap_.end() && iter->second != nullptr) {
260         iter->second->deviceName = deviceName;
261     } else {
262         SCAN_HILOGE("ScanSystemData UpdateScannerNameByUniqueId fail");
263         return false;
264     }
265     return true;
266 }
267 
UpdateScannerInfoByUniqueId(const std::string & uniqueId,const ScanDeviceInfo & scannerInfo)268 bool ScanSystemData::UpdateScannerInfoByUniqueId(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)
269 {
270     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
271     auto iter = addedScannerMap_.find(uniqueId);
272     if (iter != addedScannerMap_.end()) {
273         iter->second->deviceId = scannerInfo.deviceId;
274         iter->second->model = scannerInfo.model;
275         iter->second->deviceType = scannerInfo.deviceType;
276         iter->second->serialNumber = scannerInfo.serialNumber;
277         iter->second->deviceName = scannerInfo.deviceName;
278         iter->second->uniqueId = scannerInfo.uniqueId;
279         return true;
280     }
281     SCAN_HILOGE("ScanSystemData UpdateScannerInfoByUniqueId not found scannerInfo");
282     return false;
283 }
284 
QueryScannerNameByUniqueId(const std::string & uniqueId,std::string & deviceName)285 bool ScanSystemData::QueryScannerNameByUniqueId(const std::string &uniqueId, std::string &deviceName)
286 {
287     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
288     auto iter = addedScannerMap_.find(uniqueId);
289     if (iter != addedScannerMap_.end()) {
290         deviceName = iter->second->deviceName;
291         return true;
292     }
293     SCAN_HILOGW("QueryScannerNameByUniqueId fail");
294     return false;
295 }
296 
QueryScannerInfoByUniqueId(const std::string & uniqueId,ScanDeviceInfo & scannerInfo)297 bool ScanSystemData::QueryScannerInfoByUniqueId(const std::string &uniqueId, ScanDeviceInfo &scannerInfo)
298 {
299     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
300     for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
301         auto info = iter->second;
302         if (info == nullptr) {
303             continue;
304         }
305         std::string iterSn = info->discoverMode + info->serialNumber;
306         std::string iterUniqueId = info->discoverMode + info->uniqueId;
307         if (uniqueId == iterSn || uniqueId == iterUniqueId) {
308             scannerInfo.deviceId = info->deviceId;
309             scannerInfo.manufacturer = info->manufacturer;
310             scannerInfo.model = info->model;
311             scannerInfo.deviceType = info->deviceType;
312             scannerInfo.discoverMode = info->discoverMode;
313             scannerInfo.serialNumber = info->serialNumber;
314             scannerInfo.deviceName = info->deviceName;
315             scannerInfo.uniqueId = info->uniqueId;
316             return true;
317         }
318     }
319     return false;
320 }
321 
GetAddedScannerInfoList(std::vector<ScanDeviceInfo> & infoList)322 void ScanSystemData::GetAddedScannerInfoList(std::vector<ScanDeviceInfo> &infoList)
323 {
324     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
325     for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
326         if (iter->second != nullptr) {
327             infoList.push_back(*(iter->second));
328         }
329     }
330 }
331 
SaveScannerMap()332 bool ScanSystemData::SaveScannerMap()
333 {
334     int32_t fd = open(SCANNER_LIST_FILE.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
335     SCAN_HILOGD("SaveScannerMap fd: %{public}d", fd);
336     if (fd < 0) {
337         SCAN_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
338         return false;
339     }
340     nlohmann::json scannerMapJson = nlohmann::json::array();
341     {
342         std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
343         for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
344             auto info = iter->second;
345             if (info == nullptr) {
346                 continue;
347             }
348             nlohmann::json scannerJson = nlohmann::json::object();
349             scannerJson["deviceId"] = info->deviceId;
350             scannerJson["manufacturer"] = info->manufacturer;
351             scannerJson["model"] = info->model;
352             scannerJson["deviceType"] = info->deviceType;
353             scannerJson["discoverMode"] = info->discoverMode;
354             scannerJson["serialNumber"] = info->serialNumber;
355             scannerJson["deviceName"] = info->deviceName;
356             scannerJson["uniqueId"] = info->uniqueId;
357             scannerJson["uuid"] = info->uuid;
358             scannerMapJson.push_back(scannerJson);
359         }
360     }
361     nlohmann::json jsonObject;
362     jsonObject["version"] = SCANNER_LIST_VERSION;
363     jsonObject["scaner_list"] = scannerMapJson;
364     std::string jsonString = jsonObject.dump();
365     size_t jsonLength = jsonString.length();
366     auto writeLength = write(fd, jsonString.c_str(), jsonLength);
367     close(fd);
368     fd = -1;
369     SCAN_HILOGI("SaveScannerMap finished");
370     if (writeLength < 0) {
371         return false;
372     }
373     return (size_t)writeLength == jsonLength;
374 }
375 
IsContainScanner(const std::string & uniqueId)376 bool ScanSystemData::IsContainScanner(const std::string &uniqueId)
377 {
378     if (addedScannerMap_.find(uniqueId) != addedScannerMap_.end()) {
379         SCAN_HILOGI("The map contains the scanner.");
380         return true;
381     } else {
382         SCAN_HILOGW("The scanner is not included in the map.");
383         return false;
384     }
385 }
386 
UpdateNetScannerByUuid(const std::string & uuid,const std::string & ip)387 std::pair<std::string, std::string> ScanSystemData::UpdateNetScannerByUuid(const std::string &uuid,
388     const std::string& ip)
389 {
390     std::string oldKey;
391     std::shared_ptr<ScanDeviceInfo> scannerInfo;
392     std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
393     for (const auto& [key, info] : addedScannerMap_) {
394         if (info != nullptr && info->uuid == uuid) {
395             oldKey = key;
396             scannerInfo = info;
397             break;
398         }
399     }
400     if (oldKey == "" || scannerInfo == nullptr) {
401         SCAN_HILOGE("Cannot find scanner by uuid");
402         return std::make_pair("", "");
403     }
404     std::string oldDeviceId = scannerInfo->deviceId;
405     std::string newDeviceId = ScanUtil::ReplaceIpAddress(oldDeviceId, ip);
406     if (newDeviceId == scannerInfo->deviceId) {
407         SCAN_HILOGE("Get new device Id fail.");
408         return std::make_pair("", "");
409     }
410     SCAN_HILOGD("newdeviceId = %{private}s", newDeviceId.c_str());
411     addedScannerMap_.erase(oldKey);
412     std::string newKey = "TCP" + ip;
413     scannerInfo->deviceId = newDeviceId;
414     scannerInfo->uniqueId = ip;
415     auto it = addedScannerMap_.find(newKey);
416     if (it == addedScannerMap_.end()) {
417         addedScannerMap_.insert(std::make_pair(newKey, scannerInfo));
418     } else {
419         it->second = scannerInfo;
420     }
421     return std::make_pair(oldDeviceId, newDeviceId);
422 }
423 
424 }  // namespace Scan
425 }  // namespace OHOS