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 "vendor_ipp_everywhere.h"
17 #include "print_log.h"
18 #include <nlohmann/json.hpp>
19 
20 using namespace OHOS::Print;
21 using json = nlohmann::json;
22 namespace {
23 const std::string VENDOR_IPP_START = "ipp://";
24 const std::string VENDOR_IPP_END = ":631/ipp/print";
25 }
26 
27 static const std::string VENDOR_NAME = "driver.ipp.everywhere";
28 
VendorIppEveryWhere()29 VendorIppEveryWhere::VendorIppEveryWhere() {}
30 
~VendorIppEveryWhere()31 VendorIppEveryWhere::~VendorIppEveryWhere() {}
32 
GetVendorName()33 std::string VendorIppEveryWhere::GetVendorName()
34 {
35     return VENDOR_IPP_EVERYWHERE;
36 }
37 
Init(IPrinterVendorManager * manager)38 bool VendorIppEveryWhere::Init(IPrinterVendorManager *manager)
39 {
40     if (!VendorDriverBase::Init(manager)) {
41         PRINT_HILOGD("VendorDriverBase init fail");
42         return false;
43     }
44     return true;
45 }
UnInit()46 void VendorIppEveryWhere::UnInit()
47 {
48     VendorDriverBase::UnInit();
49 }
OnCreate()50 void VendorIppEveryWhere::OnCreate()
51 {
52     opQueue.Run();
53 }
OnDestroy()54 void VendorIppEveryWhere::OnDestroy()
55 {
56     opQueue.Stop();
57 }
OnStartDiscovery()58 void VendorIppEveryWhere::OnStartDiscovery() {}
OnStopDiscovery()59 void VendorIppEveryWhere::OnStopDiscovery() {}
60 
OnQueryCapability(const std::string & printerId,int timeout)61 bool VendorIppEveryWhere::OnQueryCapability(const std::string &printerId, int timeout)
62 {
63     auto op = std::bind(&VendorIppEveryWhere::QueryCapabilityByUri, this, printerId);
64     return opQueue.Push(op);
65 }
66 
OnQueryCapabilityByIp(const std::string & printerIp,const std::string & protocol)67 bool VendorIppEveryWhere::OnQueryCapabilityByIp(const std::string &printerIp, const std::string &protocol)
68 {
69     if (protocol != "auto" && protocol != "ipp") {
70         PRINT_HILOGW("protocol not support");
71         return false;
72     }
73     PRINT_HILOGI("QueryCapabilityByIp begin");
74     std::string uri = "ipp://" + printerIp + ":631/ipp/print";
75     auto op = std::bind(&VendorIppEveryWhere::ConnectPrinterByUri, this, uri);
76     return opQueue.Push(op);
77 }
78 
OnQueryProperties(const std::string & printerId,const std::vector<std::string> & propertyKeys)79 bool VendorIppEveryWhere::OnQueryProperties(const std::string &printerId, const std::vector<std::string> &propertyKeys)
80 {
81     bool ret = false;
82     for (auto const &key : propertyKeys) {
83         if (key == PRINTER_PROPERTY_KEY_DEVICE_STATE) {
84             auto op = std::bind(&VendorIppEveryWhere::QueryPrinterStatusByUri, this, printerId);
85             if (opQueue.Push(op)) {
86                 ret = true;
87             }
88         }
89     }
90     return ret;
91 }
92 
QueryCapabilityByUri(const std::string & uri)93 void VendorIppEveryWhere::QueryCapabilityByUri(const std::string &uri)
94 {
95     PRINT_HILOGI("QueryCapabilityByUri enter");
96     auto printerInfo = QueryPrinterInfoByUri(uri);
97     if (!UpdateCapability(printerInfo)) {
98         PRINT_HILOGW("update capability fail");
99         return;
100     }
101     PRINT_HILOGI("QueryCapabilityByUri quit");
102 }
103 
ConnectPrinterByUri(const std::string & uri)104 void VendorIppEveryWhere::ConnectPrinterByUri(const std::string &uri)
105 {
106     PRINT_HILOGI("ConnectPrinterByUri enter");
107     auto printerInfo = QueryPrinterInfoByUri(uri);
108     if (!ConnectPrinter(printerInfo)) {
109         PRINT_HILOGW("connect fail");
110         return;
111     }
112     PRINT_HILOGI("ConnectPrinterByUri quit");
113 }
114 
UpdateCapability(std::shared_ptr<PrinterInfo> printerInfo)115 bool VendorIppEveryWhere::UpdateCapability(std::shared_ptr<PrinterInfo> printerInfo)
116 {
117     if (vendorManager == nullptr) {
118         PRINT_HILOGW("vendorManager is null");
119         return false;
120     }
121     if (printerInfo == nullptr) {
122         PRINT_HILOGW("printerInfo fail");
123         return false;
124     }
125     PRINT_HILOGI("get printer info success");
126     if (vendorManager->UpdatePrinterToDiscovery(GetVendorName(), *printerInfo) != EXTENSION_ERROR_NONE) {
127         PRINT_HILOGW("UpdatePrinterToDiscovery fail");
128         return false;
129     }
130     return true;
131 }
132 
ConnectPrinter(std::shared_ptr<PrinterInfo> printerInfo)133 bool VendorIppEveryWhere::ConnectPrinter(std::shared_ptr<PrinterInfo> printerInfo)
134 {
135     if (vendorManager == nullptr) {
136         PRINT_HILOGW("vendorManager is null");
137         return false;
138     }
139     if (printerInfo == nullptr) {
140         PRINT_HILOGW("printer info fail");
141         return false;
142     }
143     PRINT_HILOGI("get printer info success");
144     std::string printerId(printerInfo->GetUri());
145     ConvertPrinterIdByUri(printerId);
146     auto discoveredInfo = vendorManager->QueryDiscoveredPrinterInfoById(GetVendorName(), printerId);
147     if (discoveredInfo != nullptr) {
148         printerInfo->SetPrinterId(printerId);
149         printerInfo->SetPrinterName(discoveredInfo->GetPrinterName());
150     }
151     if (vendorManager->UpdatePrinterToDiscovery(GetVendorName(), *printerInfo) != EXTENSION_ERROR_NONE) {
152         PRINT_HILOGW("UpdatePrinterToDiscovery fail");
153         return false;
154     }
155     PRINT_HILOGI("UpdatePrinterToDiscovery success");
156     if (vendorManager->AddPrinterToCupsWithPpd(GetVendorName(), printerInfo->GetPrinterId(), "") !=
157         EXTENSION_ERROR_NONE) {
158         PRINT_HILOGW("AddPrinterToCupsWithPpd fail");
159         return false;
160     }
161     return true;
162 }
163 
QueryPrinterInfoByUri(const std::string & uri)164 std::shared_ptr<PrinterInfo> VendorIppEveryWhere::QueryPrinterInfoByUri(const std::string &uri)
165 {
166     if (vendorManager == nullptr) {
167         PRINT_HILOGW("vendorManager is null");
168         return nullptr;
169     }
170     PrinterCapability printerCap;
171     if (!vendorManager->QueryPrinterCapabilityByUri(uri, printerCap)) {
172         PRINT_HILOGW("QueryPrinterCapabilityByUri fail");
173         return nullptr;
174     }
175     PRINT_HILOGI("QueryPrinterCapabilityByUri success");
176     return ConvertCapabilityToInfo(printerCap, uri);
177 }
178 
ConvertCapabilityToInfo(const PrinterCapability & printerCap,const std::string & printerUri)179 std::shared_ptr<PrinterInfo> VendorIppEveryWhere::ConvertCapabilityToInfo(const PrinterCapability &printerCap,
180     const std::string &printerUri)
181 {
182     if (!printerCap.HasOption()) {
183         PRINT_HILOGW("empty option");
184         return nullptr;
185     }
186     std::string capOption = printerCap.GetOption();
187     if (!json::accept(capOption)) {
188         PRINT_HILOGW("invalid option");
189         return nullptr;
190     }
191     nlohmann::json capJson = json::parse(capOption, nullptr, false);
192     if (capJson.is_discarded()) {
193         PRINT_HILOGW("json discarded");
194         return nullptr;
195     }
196     if (!capJson.contains("printerName") || !capJson["printerName"].is_string()) {
197         PRINT_HILOGW("printerName invalid");
198         return nullptr;
199     }
200     std::string printerName = capJson["printerName"].get<std::string>();
201     if (!capJson.contains("make") || !capJson["make"].is_string()) {
202         PRINT_HILOGW("make invalid");
203         return nullptr;
204     }
205     std::string printerMaker = capJson["make"].get<std::string>();
206     std::shared_ptr<PrinterInfo> printerInfo = std::make_shared<PrinterInfo>();
207     printerInfo->SetPrinterName(printerName);
208     printerInfo->SetUri(printerUri);
209     printerInfo->SetPrinterMake(printerMaker);
210     printerInfo->SetPrinterId(printerUri);
211     printerInfo->SetPrinterState(PRINTER_UPDATE_CAP);
212     printerInfo->SetCapability(printerCap);
213     nlohmann::json option;
214     option["printerName"] = printerName;
215     option["printerUri"] = printerUri;
216     option["make"] = printerMaker;
217     printerInfo->SetOption(option.dump());
218     return printerInfo;
219 }
220 
QueryPrinterStatusByUri(const std::string & uri)221 void VendorIppEveryWhere::QueryPrinterStatusByUri(const std::string &uri)
222 {
223     if (vendorManager == nullptr) {
224         PRINT_HILOGW("vendorManager is null");
225         return;
226     }
227     PrinterStatus status = PRINTER_STATUS_UNAVAILABLE;
228     if (!vendorManager->QueryPrinterStatusByUri(uri, status)) {
229         return;
230     }
231     OnPrinterStateQueried(uri, static_cast<Print_PrinterState>(status));
232 }
233 
ConvertPrinterIdByUri(std::string & uri)234 bool VendorIppEveryWhere::ConvertPrinterIdByUri(std::string &uri)
235 {
236     if (uri.empty()) {
237         return false;
238     }
239     auto pos_start = uri.find(VENDOR_IPP_START);
240     auto pos_end = uri.find(VENDOR_IPP_END);
241     if (pos_start == std::string::npos || uri.length() <= pos_start + 1 ||
242         pos_end == std::string::npos || uri.length() <= pos_end + 1) {
243         return false;
244     }
245     uri = uri.substr(pos_start + VENDOR_IPP_START.length(), pos_end - pos_start - VENDOR_IPP_START.length());
246     PRINT_HILOGD("ConvertPrinterIdByUri seccess");
247     return true;
248 }
249