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_cups_client.h"
17
18 #include <mutex>
19 #include <string>
20 #include <cups/cups-private.h>
21 #include <cups/adminutil.h>
22 #include <thread>
23 #include <algorithm>
24 #include <semaphore.h>
25 #include <csignal>
26 #include <cstdlib>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <wifi_device.h>
31 #include <wifi_p2p.h>
32 #include <wifi_p2p_msg.h>
33 #include <arpa/inet.h>
34 #include <fstream>
35 #include <sstream>
36 #include <iomanip>
37
38 #include "system_ability_definition.h"
39 #include "parameter.h"
40 #include <json/json.h>
41 #include "print_service_ability.h"
42 #include "print_log.h"
43 #include "print_constant.h"
44 #include "print_utils.h"
45 #include "print_service_converter.h"
46 #include "print_cups_attribute.h"
47 #include "print_cups_ppd.h"
48
49 namespace OHOS::Print {
50 using namespace std;
51
52 const uint32_t THOUSAND_INCH = 1000;
53 const uint32_t CUPS_SEVER_PORT = 1631;
54 const uint32_t TIME_OUT = 2000;
55 const uint32_t CONVERSION_UNIT = 2540;
56 const uint32_t LONG_TIME_OUT = 3000;
57 const uint32_t LONG_LONG_TIME_OUT = 30000;
58 const uint32_t RESOURCE_COUNT = 2;
59 const uint32_t DIR_COUNT = 3;
60 const uint32_t INDEX_ZERO = 0;
61 const uint32_t INDEX_ONE = 1;
62 const uint32_t INDEX_TWO = 2;
63 const uint32_t INDEX_THREE = 3;
64 const uint32_t MAX_RETRY_TIMES = 5;
65 const uint32_t BUFFER_LEN = 256;
66 const uint32_t DIR_MODE = 0771;
67 const uint32_t IP_RIGHT_SHIFT_0 = 0;
68 const uint32_t IP_RIGHT_SHIFT_8 = 8;
69 const uint32_t IP_RIGHT_SHIFT_16 = 16;
70 const uint32_t IP_RIGHT_SHIFT_24 = 24;
71 const uint32_t NUMBER_FOR_SPLICING_SUBSTATE = 100;
72 const uint32_t SERIAL_LENGTH = 6;
73 const uint32_t CUPSD_CONTROL_PARAM_SIZE = 96;
74 const uint32_t FREE_ONE_PRINTER = 1;
75 const uint32_t DEFAULT_BUFFER_SIZE_8K = 8192;
76 const uint32_t DEFAULT_BUFFER_SIZE_4K = 4096;
77 const uint32_t ISO_A4_WIDTH = 8268;
78 const uint32_t ISO_A4_HEIGHT = 11692;
79 const uint32_t PHOTO_5R_WIDTH = 5000;
80 const uint32_t PHOTO_5R_HEIGHT = 7000;
81 const uint32_t PHOTO_4R_WIDTH = 4000;
82 const uint32_t PHOTO_4R_HEIGHT = 6000;
83 const uint32_t MONITOR_STEP_TIME_MS = 2000;
84 const int32_t STATE_UPDATE_STEP = 5;
85
86 static const std::string CUPS_ROOT_DIR = "/data/service/el1/public/print_service/cups";
87 static const std::string DEFAULT_MAKE_MODEL = "IPP Everywhere";
88 static const std::string REMOTE_PRINTER_MAKE_MODEL = "Remote Printer";
89 static const std::string LOCAL_RAW_PRINTER_PPD_NAME = "Local Raw Printer";
90 static const std::string PRINTER_STATE_WAITING_COMPLETE = "cups-waiting-for-job-completed";
91 static const std::string PRINTER_STATE_WIFI_NOT_CONFIGURED = "wifi-not-configured-report";
92 static const std::string PRINTER_STATE_MEDIA_LOW_WARNING = "media-low-warning";
93 static const std::string PRINTER_STATE_TONER_LOW_WARNING = "toner-low-warning";
94 static const std::string PRINTER_STATE_TONER_LOW_REPORT = "toner-low-report";
95 static const std::string PRINTER_STATE_IGNORE_HP = "wifi-not-configured-report,cups-waiting-for-job-completed";
96 static const std::string PRINTER_STATE_IGNORE_BUSY =
97 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-history,cups-waiting-for-job-completed";
98 static const std::string PRINTER_STATE_IGNORE_BUSY_COMPLETED =
99 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-history";
100 static const std::string PRINTER_STATE_IGNORE_BUSY_MISSING_JOB_STATE =
101 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-state";
102 static const std::string PRINTER_STATE_IGNORE_BUSY_MISSING_JOB_STATE_COMPLETED =
103 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-state,cups-waiting-for-job-completed";
104 static const std::string PRINTER_STATE_IGNORE_TONER_LOW_JOB_STATE_COMPLETED =
105 "toner-low-warning,cups-waiting-for-job-completed";
106 static const std::string PRINTER_STATE_IGNORE_MEDIA_LOW_JOB_STATE_COMPLETED =
107 "media-low-warning,cups-waiting-for-job-completed";
108 static const std::string PRINTER_STATE_IGNORE_BUSY_WAITING_COMPLETE_OTHER_REPORT =
109 "cups-waiting-for-job-completed,other-report";
110 static const std::string PRINTER_STATE_IGNORE_BUSY_OTHER_REPORT = "other-report";
111 static const std::string PRINTER_STATE_MARKER_LOW_WARNING = "marker-supply-low-warning";
112 static const std::string PRINTER_STATE_MEDIA_EMPTY_WARNING = "media-empty-warning";
113 static const std::string PRINTER_STATE_NONE = "none";
114 static const std::string PRINTER_STATE_EMPTY = "";
115 static const std::string PRINTER_STATE_ERROR = "-error";
116 static const std::string PRINTER_STATE_WARNING = "-warning";
117 static const std::string PRINTER_STATE_REPORT = "-report";
118 static const std::string PRINTER_STATE_MEDIA_EMPTY = "media-empty";
119 static const std::string PRINTER_STATE_MEDIA_JAM = "media-jam";
120 static const std::string PRINTER_STATE_PAUSED = "paused";
121 static const std::string PRINTER_STATE_TONER_LOW = "toner-low";
122 static const std::string PRINTER_STATE_TONER_EMPTY = "toner-empty";
123 static const std::string PRINTER_STATE_DOOR_EMPTY = "door-open";
124 static const std::string PRINTER_STATE_MEDIA_NEEDED = "media-needed";
125 static const std::string PRINTER_STATE_MARKER_LOW = "marker-supply-low";
126 static const std::string PRINTER_STATE_MARKER_EMPTY = "marker-supply-empty";
127 static const std::string PRINTER_STATE_INK_EMPTY = "marker-ink-almost-empty";
128 static const std::string PRINTER_STATE_COVER_OPEN = "cover-open";
129 static const std::string PRINTER_STATE_OTHER = "other";
130 static const std::string PRINTER_STATE_OFFLINE = "offline";
131 static const std::string PRINTER_STATE_TIMED_OUT = "timed-out";
132 static const std::string PRINTER_SPOOL_AREA_FULL = "spool-area-full";
133 static const std::string JOB_STATE_REASON_PRINTER_STOP = "printer-stopped";
134 static const std::string DEFAULT_JOB_NAME = "test";
135 static const std::string CUPSD_CONTROL_PARAM = "print.cupsd.ready";
136 static const std::string USB_PRINTER = "usb";
137 static const std::string SERIAL = "serial=";
138 static const std::string PRINTER_ID_USB_PREFIX = "USB";
139 static const std::string PRINTER_MAKE_UNKNOWN = "Unknown";
140 static const std::string SPOOLER_BUNDLE_NAME = "com.ohos.spooler";
141 static const std::string VENDOR_MANAGER_PREFIX = "fwk.";
142 static const std::string DEFAULT_POLICY = "default";
143 #ifdef ENTERPRISE_ENABLE
144 static const std::string CUPS_ENTERPRISE_ROOT_DIR = "/data/service/el1/public/print_service/cups_enterprise";
145 static const std::string CUPSD_ENTERPRISE_CONTROL_PARAM = "print.cupsd_enterprise.ready";
146 #endif // ENTERPRISE_ENABLE
147
148 static const std::map<std::string, PrintJobSubState> FOLLOW_STATE_LIST {
149 { PRINTER_STATE_MEDIA_EMPTY, PRINT_JOB_BLOCKED_OUT_OF_PAPER },
150 { PRINTER_STATE_MEDIA_NEEDED, PRINT_JOB_BLOCKED_OUT_OF_PAPER },
151 { PRINTER_STATE_MEDIA_JAM, PRINT_JOB_BLOCKED_JAMMED },
152 { PRINTER_STATE_TONER_EMPTY, PRINT_JOB_BLOCKED_OUT_OF_TONER },
153 { PRINTER_STATE_TONER_LOW, PRINT_JOB_BLOCKED_LOW_ON_TONER },
154 { PRINTER_STATE_MARKER_EMPTY, PRINT_JOB_BLOCKED_OUT_OF_INK },
155 { PRINTER_STATE_INK_EMPTY, PRINT_JOB_BLOCKED_OUT_OF_INK },
156 { PRINTER_STATE_DOOR_EMPTY, PRINT_JOB_BLOCKED_DOOR_OPEN },
157 { PRINTER_STATE_COVER_OPEN, PRINT_JOB_BLOCKED_DOOR_OPEN },
158 { PRINTER_STATE_OTHER, PRINT_JOB_BLOCKED_UNKNOWN },
159 { PRINTER_STATE_TIMED_OUT, PRINT_JOB_BLOCKED_UNKNOWN },
160 { PRINTER_SPOOL_AREA_FULL, PRINT_JOB_BLOCKED_UNKNOWN },
161 };
162
163 static const std::map<std::string, map<std::string, StatePolicy>> SPECIAL_PRINTER_POLICY {
164 { "default", {{PRINTER_STATE_MEDIA_EMPTY, STATE_POLICY_BLOCK},
165 {PRINTER_STATE_MEDIA_JAM, STATE_POLICY_BLOCK}} },
166 };
167
168 std::mutex jobMutex;
169
GetUsbPrinterSerial(const std::string & deviceUri)170 std::string GetUsbPrinterSerial(const std::string &deviceUri)
171 {
172 auto pos = deviceUri.find(SERIAL);
173 if (pos == std::string::npos || pos + SERIAL.length() >= deviceUri.length()) {
174 return "";
175 }
176 std::string serial = deviceUri.substr(pos + SERIAL.length());
177 pos = serial.find("&");
178 if (pos != std::string::npos) {
179 serial = serial.substr(0, pos);
180 }
181 if (serial.length() > SERIAL_LENGTH) {
182 serial = serial.substr(serial.length() - SERIAL_LENGTH);
183 }
184 return serial;
185 }
186
187 static std::mutex g_usbPrintersLock;
188 static std::vector<PrinterInfo> g_usbPrinters;
GetUsbPrinters()189 std::vector<PrinterInfo>& GetUsbPrinters()
190 {
191 std::lock_guard<std::mutex> lock(g_usbPrintersLock);
192 return g_usbPrinters;
193 }
AddUsbPrinter(PrinterInfo & info)194 void AddUsbPrinter(PrinterInfo &info)
195 {
196 std::lock_guard<std::mutex> lock(g_usbPrintersLock);
197 g_usbPrinters.emplace_back(info);
198 }
ClearUsbPrinters()199 void ClearUsbPrinters()
200 {
201 std::lock_guard<std::mutex> lock(g_usbPrintersLock);
202 g_usbPrinters.clear();
203 }
204
205 static std::mutex g_backendPrintersLock;
206 static std::vector<PrinterInfo> g_backendPrinters;
GetBackendPrinters()207 std::vector<PrinterInfo>& GetBackendPrinters()
208 {
209 std::lock_guard<std::mutex> lock(g_backendPrintersLock);
210 return g_backendPrinters;
211 }
AddVendorPrinter(PrinterInfo & info)212 void AddVendorPrinter(PrinterInfo &info)
213 {
214 std::lock_guard<std::mutex> lock(g_backendPrintersLock);
215 g_backendPrinters.emplace_back(info);
216 }
ClearBackendPrinters()217 void ClearBackendPrinters()
218 {
219 std::lock_guard<std::mutex> lock(g_backendPrintersLock);
220 g_backendPrinters.clear();
221 }
222
ParseDeviceInfo(const char * deviceLocation,Json::Value & infoOps)223 static void ParseDeviceInfo(const char *deviceLocation, Json::Value &infoOps)
224 {
225 if (deviceLocation == nullptr) {
226 PRINT_HILOGW("deviceLocation is nullptr");
227 return;
228 }
229 PRINT_HILOGI("location = %{private}s\n", deviceLocation);
230 std::string location(deviceLocation);
231 auto pos = location.find("-");
232 if (pos == std::string::npos || pos + 1 >= location.length()) {
233 PRINT_HILOGE("can not find vid and pid");
234 return;
235 }
236 std::string vidStr = location.substr(0, pos);
237 std::string pidStr = location.substr(pos + 1);
238 std::stringstream ssVid(vidStr);
239 int vid = 0;
240 ssVid >> std::hex >> vid;
241 std::stringstream ssPid(pidStr);
242 int pid = 0;
243 ssPid >> std::hex >> pid;
244 PRINT_HILOGI("vid = %{private}d, pid = %{private}d", vid, pid);
245 infoOps["vendorId"] = vid;
246 infoOps["productId"] = pid;
247 }
248
DeviceCb(const char * deviceClass,const char * deviceId,const char * deviceInfo,const char * deviceMakeAndModel,const char * deviceUri,const char * deviceLocation,void * userData)249 void DeviceCb(const char *deviceClass, const char *deviceId, const char *deviceInfo,
250 const char *deviceMakeAndModel, const char *deviceUri, const char *deviceLocation, void *userData)
251 {
252 if (deviceClass == nullptr || deviceId == nullptr || deviceInfo == nullptr || deviceMakeAndModel == nullptr ||
253 deviceUri == nullptr) {
254 PRINT_HILOGW("null params");
255 return;
256 }
257 PRINT_HILOGD("Device: uri = %{private}s\n", deviceUri);
258 PRINT_HILOGD("class = %{private}s\n", deviceClass);
259 PRINT_HILOGD("make-and-model = %{private}s\n", deviceMakeAndModel);
260 std::string printerUri(deviceUri);
261 std::string printerMake(deviceMakeAndModel);
262 if (printerUri.length() > SERIAL_LENGTH && printerMake != PRINTER_MAKE_UNKNOWN) {
263 std::string id(deviceInfo);
264 std::string serial = GetUsbPrinterSerial(printerUri);
265 PRINT_HILOGD("serial = %{private}s\n", serial.c_str());
266 bool isUsbBackend = printerUri.substr(INDEX_ZERO, INDEX_THREE) == USB_PRINTER;
267 if (isUsbBackend) {
268 id = PRINTER_ID_USB_PREFIX + "-" + id;
269 }
270 if (!serial.empty()) {
271 id += "-" + serial;
272 }
273 PrinterInfo info;
274 info.SetPrinterId(id);
275 info.SetPrinterName(id);
276 info.SetPrinterMake(printerMake);
277 info.SetUri(printerUri);
278 info.SetPrinterState(PRINTER_ADDED);
279 PrinterCapability printerCapability;
280 info.SetCapability(printerCapability);
281 Json::Value infoOps;
282 infoOps["printerUri"] = printerUri;
283 infoOps["make"] = printerMake;
284 ParseDeviceInfo(deviceLocation, infoOps);
285 info.SetOption(PrintJsonUtil::WriteString(infoOps));
286 if (isUsbBackend) {
287 info.SetDescription("usb");
288 AddUsbPrinter(info);
289 } else {
290 info.SetDescription("vendor");
291 AddVendorPrinter(info);
292 }
293 } else {
294 PRINT_HILOGW("verify uri or make failed");
295 }
296 }
297
StandardizePrinterUri(const std::string & printerUri,const std::string & ppdName)298 std::string StandardizePrinterUri(const std::string &printerUri, const std::string &ppdName)
299 {
300 if (ppdName != BSUNI_PPD_NAME) {
301 return printerUri;
302 }
303 auto pos = printerUri.find("://");
304 if (pos == std::string::npos) {
305 return printerUri;
306 }
307 return "bsUniBackend" + printerUri.substr(pos);
308 }
309
PrintCupsClient()310 PrintCupsClient::PrintCupsClient()
311 {
312 printAbility_ = new (std::nothrow) PrintCupsWrapper();
313 }
314
~PrintCupsClient()315 PrintCupsClient::~PrintCupsClient()
316 {
317 if (printAbility_ != nullptr) {
318 delete printAbility_;
319 printAbility_ = nullptr;
320 }
321 for (auto jobItem : jobQueue_) {
322 if (jobItem != nullptr) {
323 delete jobItem;
324 jobItem = nullptr;
325 }
326 }
327 if (currentJob_ != nullptr) {
328 delete currentJob_;
329 currentJob_ = nullptr;
330 }
331 jobMonitorList_.clear();
332 }
333
334
StartCupsdServiceNotAlive()335 int32_t PrintCupsClient::StartCupsdServiceNotAlive()
336 {
337 PRINT_HILOGI("The cupsd process is not started, start it now.");
338 std::string param = GetCurCupsdControlParam();
339 int result = SetParameter(param.c_str(), "true");
340 if (result) {
341 PRINT_HILOGD("SetParameter failed: %{public}d.", result);
342 return E_PRINT_SERVER_FAILURE;
343 }
344 char value[CUPSD_CONTROL_PARAM_SIZE] = {0};
345 GetParameter(param.c_str(), "", value, CUPSD_CONTROL_PARAM_SIZE - 1);
346 PRINT_HILOGD("%{public}s value: %{public}s.", param.c_str(), value);
347 return E_PRINT_NONE;
348 }
349
StartCupsdService()350 int32_t PrintCupsClient::StartCupsdService()
351 {
352 PRINT_HILOGD("StartCupsdService enter");
353 if (!IsCupsServerAlive()) {
354 return StartCupsdServiceNotAlive();
355 }
356 std::string pidFile = GetCurCupsRootDir() + "/run/cupsd.pid";
357 struct stat sb;
358 if (stat(pidFile.c_str(), &sb) != 0) {
359 PRINT_HILOGI("stat pidFile failed.");
360 return E_PRINT_SERVER_FAILURE;
361 }
362 char realPidFile[PATH_MAX] = {};
363 if (realpath(pidFile.c_str(), realPidFile) == nullptr) {
364 PRINT_HILOGE("The realPidFile is null, errno:%{public}s", std::to_string(errno).c_str());
365 return E_PRINT_SERVER_FAILURE;
366 }
367 if (access(realPidFile, F_OK) != 0) {
368 PRINT_HILOGE("realPidFile is not exist");
369 return E_PRINT_SERVER_FAILURE;
370 }
371 FILE *file = fopen(realPidFile, "r");
372 if (file == nullptr) {
373 PRINT_HILOGE("Open pidFile error!");
374 return E_PRINT_SERVER_FAILURE;
375 }
376 if (fseek(file, 0, SEEK_SET) != 0) {
377 PRINT_HILOGE("Seek pidFile!");
378 int fcloseResult = fclose(file);
379 if (fcloseResult != 0) {
380 PRINT_HILOGE("Close File Failure.");
381 }
382 return E_PRINT_SERVER_FAILURE;
383 }
384 char buf[BUFFER_LEN] = {0};
385 if ((fread(buf, 1, BUFFER_LEN, file)) < 0) {
386 PRINT_HILOGE("Read pidFile error!");
387 int fcloseResult = fclose(file);
388 if (fcloseResult != 0) {
389 PRINT_HILOGE("Close File Failure.");
390 }
391 return E_PRINT_SERVER_FAILURE;
392 }
393 int fcloseResult = fclose(file);
394 if (fcloseResult != 0) {
395 PRINT_HILOGE("Close File Failure.");
396 return E_PRINT_SERVER_FAILURE;
397 }
398 PRINT_HILOGD("The Process of CUPSD has existed, pid: %{public}s.", buf);
399 return E_PRINT_NONE;
400 }
401
ChangeFilterPermission(const std::string & path,mode_t mode)402 bool PrintCupsClient::ChangeFilterPermission(const std::string &path, mode_t mode)
403 {
404 if (path.empty() || access(path.c_str(), F_OK) != 0) {
405 PRINT_HILOGE("File is not exist");
406 return false;
407 }
408 DIR *dir = opendir(path.c_str());
409 if (dir == nullptr) {
410 PRINT_HILOGE("Failed to open Dir: %{private}s", path.c_str());
411 return false;
412 }
413 struct dirent *entry;
414 while ((entry = readdir(dir)) != nullptr) {
415 std::string fileName = entry->d_name;
416 if (fileName == "." || fileName == "..") {
417 continue;
418 }
419 std::string filePath = path + "/" + fileName;
420 struct stat fileStat;
421 if (stat(filePath.c_str(), &fileStat) != 0) {
422 continue;
423 }
424 if (S_ISDIR(fileStat.st_mode)) {
425 ChangeFilterPermission(filePath.c_str(), mode);
426 } else if (S_ISREG(fileStat.st_mode)) {
427 if (chmod(filePath.c_str(), mode) == -1) {
428 PRINT_HILOGE("Failed to change mode");
429 }
430 }
431 }
432 closedir(dir);
433 return true;
434 }
435
SymlinkFile(std::string & srcFilePath,std::string & destFilePath)436 void PrintCupsClient::SymlinkFile(std::string &srcFilePath, std::string &destFilePath)
437 {
438 int ret = symlink(srcFilePath.c_str(), destFilePath.c_str());
439 if (!ret) {
440 PRINT_HILOGD("symlink success, ret = %{public}d, errno = %{public}d", ret, errno);
441 } else {
442 PRINT_HILOGE("symlink failed, ret = %{public}d, errno = %{public}d", ret, errno);
443 }
444 }
445
SymlinkDirectory(const char * srcDir,const char * destDir)446 void PrintCupsClient::SymlinkDirectory(const char *srcDir, const char *destDir)
447 {
448 DIR *dir = opendir(srcDir);
449 if (dir == nullptr) {
450 PRINT_HILOGE("Failed to open Dir: %{private}s", srcDir);
451 return;
452 }
453 if (access(destDir, F_OK)) {
454 mkdir(destDir, DIR_MODE);
455 } else {
456 PRINT_HILOGW("check directory failed");
457 }
458 struct dirent *file;
459 struct stat filestat = {};
460 struct stat destFilestat = {};
461 while ((file = readdir(dir)) != nullptr) {
462 if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, "..")) {
463 continue;
464 }
465 std::string srcFilePath = std::string(srcDir) + "/" + std::string(file->d_name);
466 std::string destFilePath = std::string(destDir) + "/" + std::string(file->d_name);
467
468 stat(srcFilePath.c_str(), &filestat);
469 if (S_ISDIR(filestat.st_mode)) {
470 SymlinkDirectory(srcFilePath.c_str(), destFilePath.c_str());
471 } else if (lstat(destFilePath.c_str(), &destFilestat) == 0) {
472 PRINT_HILOGD("symlink lstat %{public}s err: %{public}s", destFilePath.c_str(), strerror(errno));
473
474 if (S_ISLNK(destFilestat.st_mode)) {
475 PRINT_HILOGW("symlink already exists, continue.");
476 continue;
477 }
478 if (std::remove(destFilePath.c_str()) != 0) {
479 PRINT_HILOGE("error deleting file %{public}s err: %{public}s",
480 destFilePath.c_str(), strerror(errno));
481 continue;
482 } else {
483 PRINT_HILOGW("file successfully deleted");
484 }
485 SymlinkFile(srcFilePath, destFilePath);
486 } else {
487 PRINT_HILOGE("symlink lstat %{public}s err: %{public}s", destFilePath.c_str(), strerror(errno));
488 SymlinkFile(srcFilePath, destFilePath);
489 }
490 }
491 closedir(dir);
492 }
493
CopyDirectory(const char * srcDir,const char * destDir)494 void PrintCupsClient::CopyDirectory(const char *srcDir, const char *destDir)
495 {
496 DIR *dir = opendir(srcDir);
497 if (dir == nullptr) {
498 PRINT_HILOGE("Failed to open Dir: %{private}s", srcDir);
499 return;
500 }
501 if (access(destDir, F_OK) != 0) {
502 mkdir(destDir, DIR_MODE);
503 }
504 struct dirent *file;
505 struct stat filestat;
506 while ((file = readdir(dir)) != nullptr) {
507 if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) {
508 continue;
509 }
510 std::string srcFilePath = std::string(srcDir) + "/" + std::string(file->d_name);
511 std::string destFilePath = std::string(destDir) + "/" + std::string(file->d_name);
512
513 stat(srcFilePath.c_str(), &filestat);
514 if (S_ISDIR(filestat.st_mode)) {
515 CopyDirectory(srcFilePath.c_str(), destFilePath.c_str());
516 chmod(destFilePath.c_str(), filestat.st_mode);
517 } else {
518 char realSrc[PATH_MAX] = {};
519 char destSrc[PATH_MAX] = {};
520 if (realpath(srcFilePath.c_str(), realSrc) == nullptr ||
521 realpath(destDir, destSrc) == nullptr) {
522 PRINT_HILOGE("The realSrc is null, errno:%{public}s", std::to_string(errno).c_str());
523 continue;
524 }
525 FILE *srcFile = fopen(realSrc, "rb");
526 if (srcFile == nullptr) {
527 continue;
528 }
529 FILE *destFile = fopen(destFilePath.c_str(), "wb");
530 if (destFile == nullptr) {
531 fclose(srcFile);
532 continue;
533 }
534 char buffer[DEFAULT_BUFFER_SIZE_4K];
535 size_t bytesRead;
536 while ((bytesRead = fread(buffer, 1, sizeof(buffer), srcFile)) > 0) {
537 fwrite(buffer, 1, bytesRead, destFile);
538 }
539 fclose(srcFile);
540 fclose(destFile);
541 chmod(destFilePath.c_str(), filestat.st_mode);
542 }
543 }
544 closedir(dir);
545 }
546
GetCurCupsRootDir()547 const std::string& PrintCupsClient::GetCurCupsRootDir()
548 {
549 #ifdef ENTERPRISE_ENABLE
550 if (PrintServiceAbility::GetInstance()->IsEnterpriseEnable() &&
551 PrintServiceAbility::GetInstance()->IsEnterprise()) {
552 return CUPS_ENTERPRISE_ROOT_DIR;
553 }
554 #endif // ENTERPRISE_ENABLE
555 return CUPS_ROOT_DIR;
556 }
557
GetCurCupsdControlParam()558 const std::string& PrintCupsClient::GetCurCupsdControlParam()
559 {
560 #ifdef ENTERPRISE_ENABLE
561 if (PrintServiceAbility::GetInstance()->IsEnterpriseEnable() &&
562 PrintServiceAbility::GetInstance()->IsEnterprise()) {
563 return CUPSD_ENTERPRISE_CONTROL_PARAM;
564 }
565 #endif // ENTERPRISE_ENABLE
566 return CUPSD_CONTROL_PARAM;
567 }
568
InitCupsResources()569 int32_t PrintCupsClient::InitCupsResources()
570 {
571 std::string curDir = GetCurCupsRootDir();
572 string array[RESOURCE_COUNT][DIR_COUNT] = {
573 {"/system/bin/cups/", curDir + "/serverbin", curDir + "/serverbin/daemon"},
574 {"/system/etc/cups/share/", curDir + "/datadir", curDir + "/datadir/mime"}
575 };
576 for (uint32_t i = 0; i < RESOURCE_COUNT; i++) {
577 if (!i) {
578 SymlinkDirectory(array[i][INDEX_ZERO].c_str(), array[i][INDEX_ONE].c_str());
579 } else {
580 CopyDirectory(array[i][INDEX_ZERO].c_str(), array[i][INDEX_ONE].c_str());
581 }
582 }
583 const std::string driverDir = "/system/bin/uni_print_driver";
584 std::string srcDir = driverDir + "/filter";
585 std::string dstDir = curDir + "/serverbin/filter";
586 SymlinkDirectory(srcDir.c_str(), dstDir.c_str());
587 srcDir = driverDir + "/backend";
588 dstDir = curDir + "/serverbin/backend";
589 SymlinkDirectory(srcDir.c_str(), dstDir.c_str());
590 srcDir = "/system/bin/cups/backend/ipp";
591 dstDir = curDir + "/serverbin/backend/http";
592 SymlinkFile(srcDir, dstDir);
593 dstDir = curDir + "/serverbin/backend/ipps";
594 SymlinkFile(srcDir, dstDir);
595 return StartCupsdService();
596 }
597
StopCupsdService()598 void PrintCupsClient::StopCupsdService()
599 {
600 PRINT_HILOGD("StopCupsdService enter");
601 if (!IsCupsServerAlive()) {
602 PRINT_HILOGI("The cupsd process is not started, no need stop.");
603 return;
604 }
605 PRINT_HILOGI("The cupsd process is started, stop it now.");
606 int result = SetParameter(CUPSD_CONTROL_PARAM.c_str(), "false");
607 if (result) {
608 PRINT_HILOGD("SetParameter failed: %{public}d.", result);
609 return;
610 }
611 const int bufferSize = 96;
612 char value[bufferSize] = {0};
613 GetParameter(CUPSD_CONTROL_PARAM.c_str(), "", value, bufferSize - 1);
614 PRINT_HILOGD("print.cupsd.ready value: %{public}s.", value);
615 }
616
617 #ifdef ENTERPRISE_ENABLE
StopCupsdEnterpriseService()618 void PrintCupsClient::StopCupsdEnterpriseService()
619 {
620 PRINT_HILOGD("StopCupsdEnterpriseService enter");
621 if (!IsCupsServerAlive()) {
622 PRINT_HILOGI("The cupsd process is not started, no need stop.");
623 return;
624 }
625
626 PRINT_HILOGI("The cupsd_enterprise process is started, stop it now.");
627 int result = SetParameter(CUPSD_ENTERPRISE_CONTROL_PARAM.c_str(), "false");
628 if (result) {
629 PRINT_HILOGD("SetParameter failed: %{public}d.", result);
630 return;
631 }
632 const int bufferSize = 96;
633 char enterprise_value[bufferSize] = {0};
634 GetParameter(CUPSD_ENTERPRISE_CONTROL_PARAM.c_str(), "", enterprise_value, bufferSize - 1);
635 PRINT_HILOGD("print.cupsd_enterprise.ready value: %{public}s.", enterprise_value);
636 }
637 #endif // ENTERPRISE_ENABLE
638
QueryPPDInformation(const std::string & makeModel,std::string & ppdName)639 bool PrintCupsClient::QueryPPDInformation(const std::string &makeModel, std::string &ppdName)
640 {
641 ipp_t *request = nullptr;
642 ipp_t *response = nullptr;
643
644 if (printAbility_ == nullptr) {
645 PRINT_HILOGW("printAbility_ is null");
646 return false;
647 }
648 request = ippNewRequest(CUPS_GET_PPDS);
649 if (request == nullptr) {
650 return false;
651 }
652 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model", nullptr, makeModel.c_str());
653
654 PRINT_HILOGD("CUPS_GET_PPDS start.");
655 response = printAbility_->DoRequest(CUPS_HTTP_DEFAULT, request, "/");
656 if (response == nullptr) {
657 PRINT_HILOGE("GetAvaiablePPDS failed: %{public}s", cupsLastErrorString());
658 return false;
659 }
660 if (response->request.status.status_code > IPP_OK_CONFLICT) {
661 PRINT_HILOGE("GetAvaiablePPDS failed: %{public}s", cupsLastErrorString());
662 printAbility_->FreeRequest(response);
663 return false;
664 }
665 std::vector<std::string> ppds;
666 ParsePPDInfo(response, ppds);
667 printAbility_->FreeRequest(response);
668 if (ppds.empty()) {
669 PRINT_HILOGI("cannot find any matched ppds");
670 return false;
671 }
672 ppdName = ppds[0];
673 return true;
674 }
675
ParsePPDInfo(ipp_t * response,std::vector<std::string> & ppds)676 void PrintCupsClient::ParsePPDInfo(ipp_t *response, std::vector<std::string> &ppds)
677 {
678 if (response == nullptr) {
679 PRINT_HILOGE("ParsePPDInfo response is nullptr");
680 return;
681 }
682 for (ipp_attribute_t *attr = response->attrs; attr != nullptr; attr = attr->next) {
683 while (attr != nullptr && attr->group_tag != IPP_TAG_PRINTER) {
684 attr = attr->next;
685 }
686 if (attr == nullptr) {
687 break;
688 }
689 const char* ppd_make_model = nullptr;
690 const char* ppd_name = nullptr;
691
692 while (attr != nullptr && attr->group_tag == IPP_TAG_PRINTER) {
693 if (!strcmp(attr->name, "ppd-make-and-model") && attr->value_tag == IPP_TAG_TEXT) {
694 ppd_make_model = attr->values[0].string.text;
695 } else if (!strcmp(attr->name, "ppd-name") && attr->value_tag == IPP_TAG_NAME) {
696 ppd_name = attr->values[0].string.text;
697 }
698 attr = attr->next;
699 }
700 if (ppd_make_model != nullptr && ppd_name != nullptr) {
701 ppds.push_back(std::string(ppd_name));
702 PRINT_HILOGI("ppd: name = %{private}s, make-and-model = %{private}s", ppd_name, ppd_make_model);
703 }
704 if (attr == nullptr) {
705 break;
706 }
707 }
708 }
709
AddPrinterToCups(const std::string & printerUri,const std::string & printerName,const std::string & printerMake)710 int32_t PrintCupsClient::AddPrinterToCups(const std::string &printerUri, const std::string &printerName,
711 const std::string &printerMake)
712 {
713 PRINT_HILOGD("PrintCupsClient AddPrinterToCups start, printerMake: %{public}s", printerMake.c_str());
714 std::string ppdName = DEFAULT_PPD_NAME;
715 QueryPPDInformation(printerMake, ppdName);
716 PRINT_HILOGI("ppd driver: %{public}s", ppdName.c_str());
717 return AddPrinterToCupsWithSpecificPpd(printerUri, printerName, ppdName);
718 }
719
AddPrinterToCupsWithSpecificPpd(const std::string & printerUri,const std::string & printerName,const std::string & ppdName)720 int32_t PrintCupsClient::AddPrinterToCupsWithSpecificPpd(const std::string &printerUri, const std::string &printerName,
721 const std::string &ppdName)
722 {
723 std::string curDir = GetCurCupsRootDir();
724 if (ppdName != DEFAULT_PPD_NAME) {
725 std::string serverBin = curDir + "/serverbin";
726 mode_t permissions = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH;
727 int ret = ChangeFilterPermission(serverBin, permissions);
728 PRINT_HILOGI("ChangeFilterPermission result: %{public}d", ret);
729 }
730 PRINT_HILOGI("ppd driver: %{public}s", ppdName.c_str());
731 std::string standardName = PrintUtil::StandardizePrinterName(printerName);
732 if (IsPrinterExist(printerUri.c_str(), standardName.c_str(), ppdName.c_str())) {
733 PRINT_HILOGI("add success, printer has added");
734 return E_PRINT_NONE;
735 }
736 if (printAbility_ == nullptr) {
737 PRINT_HILOGW("printAbility_ is null");
738 return E_PRINT_SERVER_FAILURE;
739 }
740
741 ipp_t *request = nullptr;
742 char uri[HTTP_MAX_URI] = {0};
743 ippSetPort(CUPS_SEVER_PORT);
744 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
745 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", nullptr, "localhost", 0, "/printers/%s",
746 standardName.c_str());
747 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, uri);
748 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, cupsUser());
749 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", nullptr, standardName.c_str());
750 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", nullptr, printerUri.c_str());
751 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
752 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name", nullptr, ppdName.c_str());
753 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
754 PRINT_HILOGD("IPP_OP_CUPS_ADD_MODIFY_PRINTER cupsDoRequest");
755 ippDelete(printAbility_->DoRequest(nullptr, request, "/admin/"));
756 if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE) {
757 PRINT_HILOGE("add error: %{public}s", cupsLastErrorString());
758 return E_PRINT_SERVER_FAILURE;
759 }
760 PRINT_HILOGI("add success");
761 return E_PRINT_NONE;
762 }
763
AddPrinterToCupsWithPpd(const std::string & printerUri,const std::string & printerName,const std::string & ppdName,const std::string & ppdData)764 int32_t PrintCupsClient::AddPrinterToCupsWithPpd(const std::string &printerUri, const std::string &printerName,
765 const std::string &ppdName, const std::string &ppdData)
766 {
767 PRINT_HILOGD("AddPrinterToCupsWithPpd, ppdName: %{public}s", ppdName.c_str());
768 ipp_t *request = nullptr;
769 char uri[HTTP_MAX_URI] = {0};
770 std::vector<string> ppds;
771 std::string standardName = PrintUtil::StandardizePrinterName(printerName);
772 std::string standardUri = StandardizePrinterUri(printerUri, ppdName);
773 if (IsPrinterExist(standardUri.c_str(), standardName.c_str(), ppdName.c_str())) {
774 PRINT_HILOGI("add success, printer has added");
775 return E_PRINT_NONE;
776 }
777 ippSetPort(CUPS_SEVER_PORT);
778 _cupsSetError(IPP_STATUS_OK, nullptr, 0);
779 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
780 if (request == nullptr) {
781 PRINT_HILOGW("request is null");
782 return E_PRINT_SERVER_FAILURE;
783 }
784 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", nullptr, "localhost", 0, "/printers/%s",
785 standardName.c_str());
786 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, uri);
787 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, cupsUser());
788 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", nullptr, standardName.c_str());
789 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", nullptr, standardUri.c_str());
790 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
791 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
792 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-shared", 1);
793 http_status_t status = cupsSendRequest(CUPS_HTTP_DEFAULT, request, "/admin/",
794 ippLength(request) + ppdData.length());
795 if (status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA) {
796 status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, ppdData.c_str(), ppdData.length());
797 } else {
798 ippDelete(request);
799 request = nullptr;
800 PRINT_HILOGW("ppd not send, status = %{public}d", static_cast<int>(status));
801 return E_PRINT_SERVER_FAILURE;
802 }
803 ippDelete(request);
804 request = nullptr;
805 if (status != HTTP_STATUS_OK && status != HTTP_STATUS_CONTINUE) {
806 PRINT_HILOGW("add error, status = %{public}d", static_cast<int>(status));
807 return E_PRINT_SERVER_FAILURE;
808 }
809 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
810 PRINT_HILOGE("add error: %{public}s", cupsLastErrorString());
811 return E_PRINT_SERVER_FAILURE;
812 }
813 PRINT_HILOGI("add success");
814 return E_PRINT_NONE;
815 }
816
DeleteCupsPrinter(const char * printerName)817 int32_t PrintCupsClient::DeleteCupsPrinter(const char *printerName)
818 {
819 ipp_t *request = nullptr;
820 char uri[HTTP_MAX_URI] = {0};
821
822 PRINT_HILOGD("PrintCupsClient DeleteCupsPrinter start: %{private}s", printerName);
823 if (printAbility_ == nullptr) {
824 PRINT_HILOGW("printAbility_ is null");
825 return E_PRINT_SERVER_FAILURE;
826 }
827 request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
828 if (request == nullptr) {
829 PRINT_HILOGW("request is null");
830 return E_PRINT_SERVER_FAILURE;
831 }
832 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri),
833 "ipp", nullptr, "localhost", 0, "/printers/%s", printerName);
834 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, uri);
835 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, cupsUser());
836 ippDelete(printAbility_->DoRequest(nullptr, request, "/admin/"));
837 if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE) {
838 PRINT_HILOGW("DeleteCupsPrinter error: %{public}s", cupsLastErrorString());
839 }
840 return E_PRINT_NONE;
841 }
842
QueryPrinterAttributesByUri(const std::string & printerUri,const std::string & nic,int num,const char * const * pattrs)843 ipp_t *PrintCupsClient::QueryPrinterAttributesByUri(const std::string &printerUri, const std::string &nic, int num,
844 const char * const *pattrs)
845 {
846 ipp_t *request = nullptr; /* IPP Request */
847 ipp_t *response = nullptr; /* IPP Request */
848 http_t *http = nullptr;
849 char scheme[HTTP_MAX_URI] = {0}; /* Method portion of URI */
850 char username[HTTP_MAX_URI] = {0}; /* Username portion of URI */
851 char host[HTTP_MAX_URI] = {0}; /* Host portion of URI */
852 char resource[HTTP_MAX_URI] = {0}; /* Resource portion of URI */
853 int port = 0; /* Port portion of URI */
854 PRINT_HILOGD("QueryPrinterAttributesByUri enter");
855 if (printAbility_ == nullptr) {
856 PRINT_HILOGW("printAbility_ is null");
857 return nullptr;
858 }
859 httpSeparateURI(HTTP_URI_CODING_ALL, printerUri.c_str(), scheme, sizeof(scheme), username, sizeof(username), host,
860 sizeof(host), &port, resource, sizeof(resource));
861 if (host[0] == '\0' || (port != IPP_PORT && strcasestr(scheme, "ipp") == nullptr) || !IsIpAddress(host)) {
862 PRINT_HILOGW("host is empty or not ipp protocol");
863 return nullptr;
864 }
865 if (nic.empty()) {
866 http = httpConnect2(host, port, nullptr, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, TIME_OUT, nullptr);
867 } else {
868 http = httpConnect3(host, port, nullptr, AF_UNSPEC,
869 HTTP_ENCRYPTION_IF_REQUESTED, 1, TIME_OUT, nullptr, nic.c_str());
870 }
871 if (http == nullptr) {
872 PRINT_HILOGW("connect printer failed");
873 return nullptr;
874 }
875 _cupsSetError(IPP_STATUS_OK, nullptr, 0);
876 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
877 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, printerUri.c_str());
878 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, cupsUser());
879 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", num, nullptr, pattrs);
880 response = printAbility_->DoRequest(http, request, "/");
881 httpClose(http);
882 http = nullptr;
883 if (response == nullptr) {
884 PRINT_HILOGW("response is null");
885 return nullptr;
886 }
887 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
888 PRINT_HILOGE("get printer attributes error: %{public}s", cupsLastErrorString());
889 ippDelete(response);
890 response = nullptr;
891 return nullptr;
892 }
893 return response;
894 }
895
QueryPrinterCapabilityByUri(const std::string & printerUri,const std::string & printerId,PrinterCapability & printerCaps)896 int32_t PrintCupsClient::QueryPrinterCapabilityByUri(const std::string &printerUri, const std::string &printerId,
897 PrinterCapability &printerCaps)
898 {
899 PRINT_HILOGD("PrintCupsClient QueryPrinterCapabilityByUri start.");
900 static const char * const pattrs[] = { "all" };
901 std::string nic;
902 IsIpConflict(printerId, nic);
903 ipp_t *response = QueryPrinterAttributesByUri(printerUri, nic, sizeof(pattrs) / sizeof(pattrs[0]), pattrs);
904 if (response == nullptr) {
905 PRINT_HILOGW("get attributes fail");
906 return E_PRINT_SERVER_FAILURE;
907 }
908 PRINT_HILOGD("get attributes success");
909 ParsePrinterAttributesFromIPP(response, printerCaps);
910 ippDelete(response);
911 response = nullptr;
912 return E_PRINT_NONE;
913 }
914
QueryPrinterStatusByUri(const std::string & printerUri,PrinterStatus & status)915 int32_t PrintCupsClient::QueryPrinterStatusByUri(const std::string &printerUri, PrinterStatus &status)
916 {
917 PRINT_HILOGD("PrintCupsClient QueryPrinterStatusByUri start.");
918 static const char * const pattrs[] = { "printer-state" };
919 ipp_t *response = QueryPrinterAttributesByUri(printerUri, "", sizeof(pattrs) / sizeof(pattrs[0]), pattrs);
920 if (response == nullptr) {
921 PRINT_HILOGW("get attributes fail");
922 return E_PRINT_SERVER_FAILURE;
923 }
924 PRINT_HILOGD("get attributes success");
925 bool result = ParsePrinterStatusAttributes(response, status);
926 ippDelete(response);
927 response = nullptr;
928 if (!result) {
929 PRINT_HILOGW("parse state failed");
930 return E_PRINT_SERVER_FAILURE;
931 }
932 return E_PRINT_NONE;
933 }
934
QueryPrinterCapabilityFromPPD(const std::string & printerName,PrinterCapability & printerCaps,const std::string & ppdName)935 int32_t PrintCupsClient::QueryPrinterCapabilityFromPPD(const std::string &printerName, PrinterCapability &printerCaps,
936 const std::string &ppdName)
937 {
938 if (!ppdName.empty()) {
939 return QueryPrinterCapabilityFromPPDFile(printerCaps, GetCurCupsRootDir() + "/datadir/model/" + ppdName);
940 }
941 std::string standardName = PrintUtil::StandardizePrinterName(printerName);
942 PRINT_HILOGI("QueryPrinterCapabilityFromPPD printerName: %{private}s", standardName.c_str());
943
944 cups_dest_t *dest = nullptr;
945 if (printAbility_ == nullptr) {
946 PRINT_HILOGW("printAbility_ is null");
947 return E_PRINT_SERVER_FAILURE;
948 }
949 dest = printAbility_->GetNamedDest(CUPS_HTTP_DEFAULT, standardName.c_str(), nullptr);
950 if (dest == nullptr) {
951 PRINT_HILOGE("the printer is not found");
952 return E_PRINT_SERVER_FAILURE;
953 }
954 cups_dinfo_t *dinfo = printAbility_->CopyDestInfo(CUPS_HTTP_DEFAULT, dest);
955 if (dinfo == nullptr) {
956 PRINT_HILOGE("cupsCopyDestInfo failed");
957 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
958 return E_PRINT_SERVER_FAILURE;
959 }
960
961 ParsePrinterAttributesFromIPP(dinfo->attrs, printerCaps);
962 printerCaps.Dump();
963
964 printAbility_->FreeDestInfo(dinfo);
965 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
966 PRINT_HILOGI("QueryPrinterCapabilityFromPPD out\n");
967 return E_PRINT_NONE;
968 }
969
AddCupsPrintJob(const PrintJob & jobInfo,const std::string & userName)970 void PrintCupsClient::AddCupsPrintJob(const PrintJob &jobInfo, const std::string &userName)
971 {
972 JobParameters *jobParams = BuildJobParameters(jobInfo, userName);
973 if (jobParams == nullptr) {
974 PRINT_HILOGE("AddCupsPrintJob Params is nullptr");
975 return;
976 }
977 DumpJobParameters(jobParams);
978 jobQueue_.push_back(jobParams);
979 StartNextJob();
980 }
981
GetNextJob()982 JobParameters *PrintCupsClient::GetNextJob()
983 {
984 if (jobQueue_.empty()) {
985 PRINT_HILOGE("no active job in jobQueue_");
986 return nullptr;
987 }
988 if (currentJob_ != nullptr) {
989 JobParameters *lastJob = jobQueue_.back();
990 if (lastJob != nullptr) {
991 PrintServiceAbility::GetInstance()->UpdatePrintJobState(lastJob->serviceJobId, PRINT_JOB_QUEUED,
992 PRINT_JOB_BLOCKED_UNKNOWN);
993 }
994 PRINT_HILOGE("a active job is sending, job len: %{public}zd", jobQueue_.size());
995 return nullptr;
996 }
997 PRINT_HILOGI("start next job from queue");
998
999 std::lock_guard<std::mutex> lock(jobMutex);
1000 currentJob_ = jobQueue_.at(0);
1001 jobQueue_.erase(jobQueue_.begin());
1002 return currentJob_;
1003 }
1004
StartNextJob()1005 void PrintCupsClient::StartNextJob()
1006 {
1007 auto nextJob = GetNextJob();
1008 if (nextJob == nullptr) {
1009 PRINT_HILOGW("nextJob is nullptr");
1010 return;
1011 }
1012 if (toCups_) {
1013 auto self = shared_from_this();
1014 CallbackFunc callback = [self]() { self->JobSentCallback(); };
1015 std::thread StartPrintThread([self, callback] {self->StartCupsJob(self->currentJob_, callback);});
1016 StartPrintThread.detach();
1017 }
1018 }
1019
JobSentCallback()1020 void PrintCupsClient::JobSentCallback()
1021 {
1022 PRINT_HILOGI("Previous job send success, start next job");
1023 if (currentJob_ != nullptr) {
1024 PrintServiceAbility::GetInstance()->FlushCacheFileToUserData(currentJob_->serviceJobId);
1025 delete currentJob_;
1026 currentJob_ = nullptr;
1027 }
1028 StartNextJob();
1029 }
1030
FillBorderlessOptions(JobParameters * jobParams,int num_options,cups_option_t ** options)1031 int PrintCupsClient::FillBorderlessOptions(JobParameters *jobParams, int num_options, cups_option_t **options)
1032 {
1033 if (jobParams == nullptr) {
1034 PRINT_HILOGE("FillBorderlessOptions Params is nullptr");
1035 return num_options;
1036 }
1037 if (jobParams->mediaType.find(CUPS_MEDIA_TYPE_PHOTO) != std::string::npos && jobParams->borderless) {
1038 PRINT_HILOGD("borderless job options");
1039 num_options = cupsAddOption("print-scaling", "fill", num_options, options);
1040 std::vector<MediaSize> mediaSizes;
1041 mediaSizes.push_back({ CUPS_MEDIA_A4, ISO_A4_WIDTH, ISO_A4_HEIGHT });
1042 mediaSizes.push_back({ CUPS_MEDIA_4X6, PHOTO_4R_WIDTH, PHOTO_4R_HEIGHT });
1043 mediaSizes.push_back({ CUPS_MEDIA_5X7, PHOTO_5R_WIDTH, PHOTO_5R_HEIGHT });
1044 int sizeIndex = -1;
1045 float meidaWidth = 0;
1046 float mediaHeight = 0;
1047 for (int i = 0; i < static_cast<int>(mediaSizes.size()); i++) {
1048 if (mediaSizes[i].name == jobParams->mediaSize) {
1049 sizeIndex = i;
1050 break;
1051 }
1052 }
1053 if (sizeIndex >= 0) {
1054 meidaWidth = floorf(ConvertInchTo100MM(mediaSizes[sizeIndex].WidthInInches));
1055 mediaHeight = floorf(ConvertInchTo100MM(mediaSizes[sizeIndex].HeightInInches));
1056 } else {
1057 meidaWidth = floorf(ConvertInchTo100MM(mediaSizes[0].WidthInInches));
1058 mediaHeight = floorf(ConvertInchTo100MM(mediaSizes[0].HeightInInches));
1059 }
1060 std::stringstream value;
1061 value << "{media-size={x-dimension=" << meidaWidth << " y-dimension=" << mediaHeight;
1062 value << "} media-bottom-margin=" << 0 << " media-left-margin=" << 0 << " media-right-margin=" << 0;
1063 value << " media-top-margin=" << 0 << " media-type=\"" << jobParams->mediaType << "\"}";
1064 PRINT_HILOGD("value: %s", value.str().c_str());
1065 num_options = cupsAddOption("media-col", value.str().c_str(), num_options, options);
1066 } else {
1067 PRINT_HILOGD("not borderless job options");
1068 num_options = cupsAddOption("fit-to-page", "true", num_options, options);
1069 if (!jobParams->mediaSize.empty()) {
1070 num_options = cupsAddOption(CUPS_MEDIA, jobParams->mediaSize.c_str(), num_options, options);
1071 } else {
1072 num_options = cupsAddOption(CUPS_MEDIA, CUPS_MEDIA_A4, num_options, options);
1073 }
1074 if (!jobParams->mediaType.empty()) {
1075 num_options = cupsAddOption(CUPS_MEDIA_TYPE, jobParams->mediaType.c_str(), num_options, options);
1076 } else {
1077 num_options = cupsAddOption(CUPS_MEDIA_TYPE, CUPS_MEDIA_TYPE_PLAIN, num_options, options);
1078 }
1079 }
1080 return num_options;
1081 }
1082
FillLandscapeOptions(JobParameters * jobParams,int num_options,cups_option_t ** options)1083 int PrintCupsClient::FillLandscapeOptions(JobParameters *jobParams, int num_options, cups_option_t **options)
1084 {
1085 if (jobParams->isAutoRotate) {
1086 PRINT_HILOGE("AutoRotate is Open, skip FillLandscapeOptions");
1087 return num_options;
1088 }
1089 num_options = cupsAddOption("pdfAutoRotate", "false", num_options, options);
1090 if (jobParams->isLandscape) {
1091 num_options = cupsAddOption(CUPS_ORIENTATION, CUPS_ORIENTATION_LANDSCAPE, num_options, options);
1092 } else {
1093 num_options = cupsAddOption(CUPS_ORIENTATION, CUPS_ORIENTATION_PORTRAIT, num_options, options);
1094 }
1095 return num_options;
1096 }
1097
FillJobOptions(JobParameters * jobParams,int num_options,cups_option_t ** options)1098 int PrintCupsClient::FillJobOptions(JobParameters *jobParams, int num_options, cups_option_t **options)
1099 {
1100 if (jobParams == nullptr) {
1101 PRINT_HILOGE("FillJobOptions Params is nullptr");
1102 return num_options;
1103 }
1104 if (jobParams->numCopies >= 1) {
1105 num_options = cupsAddIntegerOption(CUPS_COPIES, jobParams->numCopies, num_options, options);
1106 } else {
1107 num_options = cupsAddIntegerOption(CUPS_COPIES, 1, num_options, options);
1108 }
1109
1110 if (!jobParams->duplex.empty()) {
1111 num_options = cupsAddOption(CUPS_SIDES, jobParams->duplex.c_str(), num_options, options);
1112 } else {
1113 num_options = cupsAddOption(CUPS_SIDES, CUPS_SIDES_ONE_SIDED, num_options, options);
1114 }
1115 if (!jobParams->printQuality.empty()) {
1116 num_options = cupsAddOption(CUPS_PRINT_QUALITY, jobParams->printQuality.c_str(), num_options, options);
1117 } else {
1118 num_options = cupsAddOption(CUPS_PRINT_QUALITY, CUPS_PRINT_QUALITY_NORMAL, num_options, options);
1119 }
1120 if (!jobParams->color.empty()) {
1121 num_options = cupsAddOption(CUPS_PRINT_COLOR_MODE, jobParams->color.c_str(), num_options, options);
1122 } else {
1123 num_options = cupsAddOption(CUPS_PRINT_COLOR_MODE, CUPS_PRINT_COLOR_MODE_AUTO, num_options, options);
1124 }
1125
1126 num_options = FillLandscapeOptions(jobParams, num_options, options);
1127
1128 if (jobParams->isCollate) {
1129 num_options = cupsAddOption("Collate", "true", num_options, options);
1130 } else {
1131 num_options = cupsAddOption("Collate", "false", num_options, options);
1132 }
1133 if (jobParams->isReverse) {
1134 num_options = cupsAddOption("OutputOrder", "Reverse", num_options, options);
1135 } else {
1136 num_options = cupsAddOption("OutputOrder", "Normal", num_options, options);
1137 }
1138 std::string nic;
1139 if (IsIpConflict(jobParams->printerId, nic)) {
1140 num_options = cupsAddOption("nic", nic.c_str(), num_options, options);
1141 }
1142 num_options = FillBorderlessOptions(jobParams, num_options, options);
1143 num_options = FillAdvancedOptions(jobParams, num_options, options);
1144 return num_options;
1145 }
1146
FillAdvancedOptions(JobParameters * jobParams,int num_options,cups_option_t ** options)1147 int PrintCupsClient::FillAdvancedOptions(JobParameters *jobParams, int num_options, cups_option_t **options)
1148 {
1149 if (jobParams->advancedOpsJson.isNull()) {
1150 PRINT_HILOGE("advanced options are null.");
1151 return num_options;
1152 }
1153
1154 Json::Value::Members keys = jobParams->advancedOpsJson.getMemberNames();
1155 for (auto key = keys.begin(); key != keys.end(); key++) {
1156 std::string keyStr = *key;
1157 if (jobParams->advancedOpsJson.isMember(keyStr) || jobParams->advancedOpsJson[keyStr].isString()) {
1158 std::string valueStr = jobParams->advancedOpsJson[keyStr].asString();
1159 num_options = cupsAddOption(keyStr.c_str(), valueStr.c_str(), num_options, options);
1160 }
1161 }
1162 return num_options;
1163 }
1164
QueryAddedPrinterList(std::vector<std::string> & printerNameList)1165 int32_t PrintCupsClient::QueryAddedPrinterList(std::vector<std::string> &printerNameList)
1166 {
1167 if (!IsCupsServerAlive()) {
1168 PRINT_HILOGI("The cupsd process is not started, start it now.");
1169 int32_t ret = StartCupsdService();
1170 if (ret != 0) {
1171 return E_PRINT_SERVER_FAILURE;
1172 }
1173 }
1174 printerNameList.clear();
1175 cups_dest_t *dests = nullptr;
1176 int num = cupsGetDests(&dests);
1177 PRINT_HILOGI("QueryAddedPrinterList, num: %{public}d.", num);
1178 for (int i = 0; i < num; i++) {
1179 PRINT_HILOGD("QueryAddedPrinterList, printerIsDefault: %{public}d.", dests[i].is_default);
1180 printerNameList.emplace_back(dests[i].name);
1181 }
1182 cupsFreeDests(num, dests);
1183 return E_PRINT_NONE;
1184 }
1185
SetDefaultPrinter(const std::string & printerName)1186 int32_t PrintCupsClient::SetDefaultPrinter(const std::string &printerName)
1187 {
1188 http_t *http = nullptr;
1189 if (printAbility_ == nullptr) {
1190 PRINT_HILOGW("printAbility_ is null");
1191 return E_PRINT_SERVER_FAILURE;
1192 }
1193 ippSetPort(CUPS_SEVER_PORT);
1194 http = httpConnect2(cupsServer(), ippPort(), nullptr,
1195 AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, LONG_TIME_OUT, nullptr);
1196 if (http == nullptr) {
1197 PRINT_HILOGE("cups server is not alive");
1198 return E_PRINT_SERVER_FAILURE;
1199 }
1200 ipp_t *request = nullptr; /* IPP Request */
1201 char uri[HTTP_MAX_URI] = {0}; /* URI for printer/class */
1202 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", nullptr,
1203 "localhost", 0, "/printers/%s", printerName.c_str());
1204 request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
1205 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1206 "printer-uri", nullptr, uri);
1207 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1208 nullptr, cupsUser());
1209 ippDelete(printAbility_->DoRequest(http, request, "/admin/"));
1210 httpClose(http);
1211
1212 const char* default_printer = cupsGetDefault();
1213 PRINT_HILOGI("default_printer=%{public}s", default_printer);
1214 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
1215 PRINT_HILOGI("[ERROR] occur a error when do cups-request{setDefault}. error is:> ");
1216 return E_PRINT_SERVER_FAILURE;
1217 }
1218 return E_PRINT_NONE;
1219 }
1220
GetPPDFile(const std::string & printerName)1221 ppd_file_t* PrintCupsClient::GetPPDFile(const std::string &printerName)
1222 {
1223 if (!IsCupsServerAlive()) {
1224 PRINT_HILOGI("The cupsd process is not started, start it now.");
1225 int32_t ret = StartCupsdService();
1226 if (ret != 0) {
1227 PRINT_HILOGE("The cupsd process start fail.");
1228 return nullptr;
1229 }
1230 }
1231 if (printerName.find("../") == 0) {
1232 PRINT_HILOGE("GetPPDFile printerName is out of fileDir");
1233 return nullptr;
1234 }
1235 ppd_file_t *ppd = 0;
1236 std::string fileDir = GetCurCupsRootDir() + "/ppd/";
1237 std::string pName = printerName;
1238 std::string filePath = fileDir + pName + ".ppd";
1239 PRINT_HILOGI("GetPPDFile started filePath %{public}s", filePath.c_str());
1240 char realPath[PATH_MAX] = {};
1241 if (realpath(filePath.c_str(), realPath) == nullptr) {
1242 PRINT_HILOGE("The realPidFile is null, errno:%{public}s", std::to_string(errno).c_str());
1243 return nullptr;
1244 }
1245 int fd;
1246 if ((fd = open(realPath, O_RDWR)) < 0) {
1247 PRINT_HILOGE("Open ppdFile error!");
1248 return nullptr;
1249 }
1250 fdsan_exchange_owner_tag(fd, 0, PRINT_LOG_DOMAIN);
1251 PRINT_HILOGI("GetPPDFile %{public}d", fd);
1252 ppd = ppdOpenFd(fd);
1253 fdsan_close_with_tag(fd, PRINT_LOG_DOMAIN);
1254 if (ppd == nullptr) {
1255 PRINT_HILOGE("ppdfile open is nullptr");
1256 } else {
1257 PRINT_HILOGI("GetPPDFile groups:%{public}d,pagesize_num:%{public}d", ppd->num_groups, ppd->num_sizes);
1258 }
1259 return ppd;
1260 }
1261
QueryPrinterAttrList(const std::string & printerName,const std::vector<std::string> & keyList,std::vector<std::string> & valueList)1262 int32_t PrintCupsClient::QueryPrinterAttrList(const std::string &printerName, const std::vector<std::string> &keyList,
1263 std::vector<std::string> &valueList)
1264 {
1265 if (printAbility_ == nullptr) {
1266 PRINT_HILOGW("printAbility_ is null");
1267 return E_PRINT_SERVER_FAILURE;
1268 }
1269 cups_dest_t *dest = nullptr;
1270 dest = printAbility_->GetNamedDest(CUPS_HTTP_DEFAULT, printerName.c_str(), nullptr);
1271 if (dest == nullptr) {
1272 PRINT_HILOGW("the printer is not found");
1273 return E_PRINT_SERVER_FAILURE;
1274 }
1275 for (const auto &key : keyList) {
1276 const char *ret = cupsGetOption(key.c_str(), dest->num_options, dest->options);
1277 if (ret != nullptr) {
1278 std::string valueStr = ret;
1279 std::string value = key + "&" + valueStr;
1280 valueList.emplace_back(value);
1281 }
1282 }
1283 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
1284 PRINT_HILOGI("QueryPrinterAttr end");
1285 return E_PRINT_NONE;
1286 }
1287
QueryPrinterInfoByPrinterId(const std::string & printerId,PrinterInfo & info)1288 int32_t PrintCupsClient::QueryPrinterInfoByPrinterId(const std::string &printerId, PrinterInfo &info)
1289 {
1290 PRINT_HILOGD("the printerInfo printerName %{public}s", info.GetPrinterName().c_str());
1291 if (printAbility_ == nullptr) {
1292 PRINT_HILOGW("printAbility_ is null");
1293 return E_PRINT_SERVER_FAILURE;
1294 }
1295 cups_dest_t *dest = nullptr;
1296 dest = printAbility_->GetNamedDest(CUPS_HTTP_DEFAULT, info.GetPrinterName().c_str(), nullptr);
1297 if (dest == nullptr) {
1298 PRINT_HILOGW("the printer is not found");
1299 return E_PRINT_SERVER_FAILURE;
1300 }
1301 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
1302 if (info.HasOption()) {
1303 PRINT_HILOGI("the printerInfo option");
1304 PrinterCapability printerCaps;
1305 std::string infoOpt = info.GetOption();
1306 PRINT_HILOGD("the printerInfo option %{public}s", infoOpt.c_str());
1307 Json::Value infoJson;
1308 if (!PrintJsonUtil::Parse(infoOpt, infoJson)) {
1309 PRINT_HILOGE("infoOpt can not parse to json object");
1310 return E_PRINT_INVALID_PARAMETER;
1311 }
1312 if (!PrintJsonUtil::IsMember(infoJson, "printerUri") || !infoJson["printerUri"].isString()) {
1313 PRINT_HILOGE("The infoJson does not have a necessary printerUri attribute.");
1314 return E_PRINT_INVALID_PARAMETER;
1315 }
1316 std::string printerUri = infoJson["printerUri"].asString();
1317 PRINT_HILOGD("QueryPrinterInfoByPrinterId in %{public}s", printerUri.c_str());
1318 if (PrintJsonUtil::IsMember(infoJson, "printerName") && infoJson["printerName"].isString()) {
1319 info.SetPrinterName(infoJson["printerName"].asString());
1320 }
1321 int32_t ret = QueryPrinterCapabilityByUri(printerUri, printerId, printerCaps);
1322 PRINT_HILOGI("QueryPrinterInfoByPrinterId out");
1323 if (ret != 0) {
1324 PRINT_HILOGE("QueryPrinterInfoByPrinterId QueryPrinterCapabilityByUri fail");
1325 return E_PRINT_SERVER_FAILURE;
1326 }
1327 Json::Value cupsOptionsJson = printerCaps.GetPrinterAttrGroupJson();
1328 infoJson["cupsOptions"] = cupsOptionsJson;
1329 info.SetOption(PrintJsonUtil::WriteString(infoJson));
1330 info.Dump();
1331 }
1332 return E_PRINT_NONE;
1333 }
1334
CheckPrinterMakeModel(JobParameters * jobParams,bool & driverMissing)1335 bool PrintCupsClient::CheckPrinterMakeModel(JobParameters *jobParams, bool &driverMissing)
1336 {
1337 cups_dest_t *dest = nullptr;
1338 bool isMakeModelRight = false;
1339 uint32_t retryCount = 0;
1340 PRINT_HILOGD("CheckPrinterMakeModel start.");
1341 if (jobParams == nullptr) {
1342 PRINT_HILOGE("The jobParams is null");
1343 return isMakeModelRight;
1344 }
1345 if (printAbility_ == nullptr) {
1346 PRINT_HILOGW("printAbility_ is null");
1347 return isMakeModelRight;
1348 }
1349 const uint32_t GET_OPTION_TIMES = 40;
1350 while (retryCount < GET_OPTION_TIMES) {
1351 dest = printAbility_->GetNamedDest(CUPS_HTTP_DEFAULT, jobParams->printerName.c_str(), nullptr);
1352 if (dest != nullptr) {
1353 const char *makeModel = cupsGetOption("printer-make-and-model", dest->num_options, dest->options);
1354 if (makeModel == nullptr || strcmp(makeModel, "Local Raw Printer") == 0) {
1355 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
1356 retryCount++;
1357 sleep(INDEX_TWO);
1358 continue;
1359 }
1360 PRINT_HILOGD("makeModel=%{private}s", makeModel);
1361 if (!CheckPrinterDriverExist(std::string(makeModel))) {
1362 driverMissing = true;
1363 break;
1364 }
1365 isMakeModelRight = true;
1366 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
1367 break;
1368 } else {
1369 PRINT_HILOGE("The dest is null");
1370 }
1371 retryCount++;
1372 sleep(INDEX_TWO);
1373 }
1374 return isMakeModelRight;
1375 }
1376
CheckPrinterDriverExist(const std::string & makeModel)1377 bool PrintCupsClient::CheckPrinterDriverExist(const std::string &makeModel)
1378 {
1379 if (makeModel.empty()) {
1380 PRINT_HILOGE("makeModel empty");
1381 return false;
1382 }
1383 if (strstr(makeModel.c_str(), DEFAULT_MAKE_MODEL.c_str()) != nullptr ||
1384 strstr(makeModel.c_str(), BSUNI_PPD_NAME.c_str()) != nullptr) {
1385 PRINT_HILOGI("skip check printer driver exist");
1386 return true;
1387 }
1388 std::string ppdName;
1389 QueryPPDInformation(makeModel, ppdName);
1390 return !ppdName.empty();
1391 }
1392
VerifyPrintJob(JobParameters * jobParams,int & num_options,uint32_t & jobId,cups_option_t * options,http_t * http)1393 bool PrintCupsClient::VerifyPrintJob(JobParameters *jobParams, int &num_options, uint32_t &jobId,
1394 cups_option_t *options, http_t *http)
1395 {
1396 if (jobParams == nullptr) {
1397 PRINT_HILOGE("The jobParams is null");
1398 return false;
1399 }
1400 uint32_t retryCount = 0;
1401 bool isPrinterOnline = false;
1402 auto monitorParams = std::make_shared<JobMonitorParam>(jobParams->serviceAbility, jobParams->serviceJobId,
1403 jobId, jobParams->printerUri, jobParams->printerName, jobParams->printerId, http);
1404 while (retryCount < MAX_RETRY_TIMES) {
1405 if (CheckPrinterOnline(monitorParams)) {
1406 isPrinterOnline = true;
1407 break;
1408 }
1409 retryCount++;
1410 sleep(INDEX_ONE);
1411 }
1412 if (!isPrinterOnline) {
1413 PRINT_HILOGE("VerifyPrintJob printer is offline.");
1414 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, PRINT_JOB_BLOCKED,
1415 PRINT_JOB_BLOCKED_OFFLINE);
1416 return false;
1417 }
1418 bool driverMissing = false;
1419 if (!CheckPrinterMakeModel(jobParams, driverMissing)) {
1420 PRINT_HILOGE("VerifyPrintJob printer make model is error");
1421 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, PRINT_JOB_BLOCKED,
1422 driverMissing ? PRINT_JOB_BLOCKED_DRIVER_MISSING : PRINT_JOB_BLOCKED_DRIVER_EXCEPTION);
1423 return false;
1424 }
1425 num_options = FillJobOptions(jobParams, num_options, &options);
1426 cupsSetUser(jobParams->jobOriginatingUserName.c_str());
1427 if ((jobId = static_cast<uint32_t>(cupsCreateJob(http, jobParams->printerName.c_str(), jobParams->jobName.c_str(),
1428 num_options, options))) == 0) {
1429 PRINT_HILOGE("Unable to cupsCreateJob: %{public}s", cupsLastErrorString());
1430 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, PRINT_JOB_BLOCKED,
1431 PRINT_JOB_BLOCKED_SERVER_CONNECTION_ERROR);
1432 return false;
1433 }
1434 return true;
1435 }
1436
HandleFiles(JobParameters * jobParams,uint32_t num_files,http_t * http,uint32_t jobId)1437 bool PrintCupsClient::HandleFiles(JobParameters *jobParams, uint32_t num_files, http_t *http, uint32_t jobId)
1438 {
1439 if (jobParams == nullptr) {
1440 PRINT_HILOGW("jobParams is null");
1441 return false;
1442 }
1443 cups_file_t *fp = nullptr;
1444 http_status_t status;
1445 char buffer[DEFAULT_BUFFER_SIZE_8K];
1446 ssize_t bytes = -1;
1447
1448 for (uint32_t i = 0; i < num_files; i++) {
1449 if ((fp = cupsFileOpenFd(jobParams->fdList[i], "rb")) == nullptr) {
1450 PRINT_HILOGE("Unable to open print file, cancel the job");
1451 cupsCancelJob2(http, jobParams->printerName.c_str(), jobId, 0);
1452 UpdatePrintJobStateInJobParams(jobParams, PRINT_JOB_BLOCKED, PRINT_JOB_COMPLETED_FILE_CORRUPT);
1453 return false;
1454 }
1455 status = cupsStartDocument(http, jobParams->printerName.c_str(), jobId, jobParams->jobName.c_str(),
1456 jobParams->documentFormat.c_str(), i == (num_files - 1));
1457 if (status == HTTP_STATUS_CONTINUE) {
1458 bytes = cupsFileRead(fp, buffer, sizeof(buffer));
1459 }
1460 while (status == HTTP_STATUS_CONTINUE && bytes > 0) {
1461 status = cupsWriteRequestData(http, buffer, (size_t)bytes);
1462 bytes = cupsFileRead(fp, buffer, sizeof(buffer));
1463 }
1464 cupsFileClose(fp);
1465 if (status != HTTP_STATUS_CONTINUE || cupsFinishDocument(http, jobParams->printerName.c_str())
1466 != IPP_STATUS_OK) {
1467 PRINT_HILOGE("Unable to queue, error is %{public}s, cancel the job and return...", cupsLastErrorString());
1468 cupsCancelJob2(http, jobParams->printerUri.c_str(), jobId, 0);
1469 UpdatePrintJobStateInJobParams(jobParams, PRINT_JOB_BLOCKED, PRINT_JOB_BLOCKED_UNKNOWN);
1470 return false;
1471 }
1472 }
1473 return true;
1474 }
1475
StartCupsJob(JobParameters * jobParams,CallbackFunc callback)1476 void PrintCupsClient::StartCupsJob(JobParameters *jobParams, CallbackFunc callback)
1477 {
1478 http_t *http = nullptr;
1479 int num_options = 0;
1480 cups_option_t *options = nullptr;
1481 uint32_t jobId = 0;
1482
1483 if (!VerifyPrintJob(jobParams, num_options, jobId, options, http)) {
1484 callback();
1485 PRINT_HILOGE("verify print job failed");
1486 return;
1487 }
1488 if (ResumePrinter(jobParams->printerName)) {
1489 PRINT_HILOGW("ResumePrinter fail");
1490 }
1491 uint32_t num_files = jobParams->fdList.size();
1492 PRINT_HILOGD("StartCupsJob fill job options, num_files: %{public}d", num_files);
1493 if (jobParams->isCanceled || !HandleFiles(jobParams, num_files, http, jobId)) {
1494 callback();
1495 return;
1496 }
1497 http_t *monitorHttp = nullptr;
1498 ippSetPort(CUPS_SEVER_PORT);
1499 monitorHttp = httpConnect2(cupsServer(), ippPort(), nullptr, AF_UNSPEC,
1500 HTTP_ENCRYPTION_IF_REQUESTED, 1, LONG_TIME_OUT, nullptr);
1501 if (monitorHttp == nullptr) {
1502 return;
1503 }
1504 jobParams->cupsJobId = jobId;
1505 PRINT_HILOGD("start job success, jobId: %{public}d", jobId);
1506 auto monitorParams = std::make_shared<JobMonitorParam>(jobParams->serviceAbility, jobParams->serviceJobId,
1507 jobId, jobParams->printerUri, jobParams->printerName, jobParams->printerId, monitorHttp);
1508 BuildMonitorPolicy(monitorParams);
1509 PRINT_HILOGD("MonitorJobState enter, cupsJobId: %{public}d", monitorParams->cupsJobId);
1510 monitorParams->jobOriginatingUserName = jobParams->jobOriginatingUserName;
1511 {
1512 std::lock_guard<std::mutex> lock(jobMonitorMutex_);
1513 if (jobMonitorList_.empty()) {
1514 jobMonitorList_.push_back(monitorParams);
1515 auto self = shared_from_this();
1516 std::thread startMonitotThread([self] { self->StartMonitor(); });
1517 startMonitotThread.detach();
1518 } else {
1519 jobMonitorList_.push_back(monitorParams);
1520 }
1521 }
1522 callback();
1523 }
1524
BuildMonitorPolicy(std::shared_ptr<JobMonitorParam> monitorParams)1525 void PrintCupsClient::BuildMonitorPolicy(std::shared_ptr<JobMonitorParam> monitorParams)
1526 {
1527 if (monitorParams == nullptr) {
1528 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1529 return;
1530 }
1531 PrinterInfo addedPrinterInfo;
1532 if (PrintServiceAbility::GetInstance()->QueryPrinterInfoByPrinterId(monitorParams->printerId,
1533 addedPrinterInfo) != E_PRINT_NONE) {
1534 PRINT_HILOGW("printer make is empty, use default policy");
1535 return;
1536 }
1537 auto policyPair = SPECIAL_PRINTER_POLICY.find(addedPrinterInfo.GetPrinterMake());
1538 if (policyPair == SPECIAL_PRINTER_POLICY.end()) {
1539 PRINT_HILOGI("normal printer, use default policy");
1540 policyPair = SPECIAL_PRINTER_POLICY.find(DEFAULT_POLICY);
1541 }
1542 PRINT_HILOGI("special printer, update policy");
1543 int32_t index = 0;
1544 for (auto stateItem = FOLLOW_STATE_LIST.begin(); stateItem != FOLLOW_STATE_LIST.end(); stateItem++) {
1545 auto statePair = policyPair->second.find(stateItem->first);
1546 if (statePair != policyPair->second.end()) {
1547 monitorParams->policyArray[index] = statePair->second;
1548 }
1549 index++;
1550 }
1551 }
1552
StartMonitor()1553 void PrintCupsClient::StartMonitor()
1554 {
1555 PRINT_HILOGI("state monitor start");
1556 ippSetPort(CUPS_SEVER_PORT);
1557 std::vector<std::shared_ptr<JobMonitorParam>> jobMonitorList;
1558 while (!jobMonitorList_.empty()) {
1559 uint64_t lastUpdateTime = GetNowTime();
1560 {
1561 std::lock_guard<std::mutex> lock(jobMonitorMutex_);
1562 jobMonitorList = jobMonitorList_;
1563 }
1564 for (auto monitorParams : jobMonitorList) {
1565 if (!IfContinueToHandleJobState(monitorParams)) {
1566 PRINT_HILOGI("delete a completed job");
1567 std::lock_guard<std::mutex> lock(jobMonitorMutex_);
1568 auto item = find(jobMonitorList_.begin(), jobMonitorList_.end(), monitorParams);
1569 jobMonitorList_.erase(item);
1570 }
1571 }
1572 uint64_t currentTime = GetNowTime();
1573 if (currentTime < lastUpdateTime + MONITOR_STEP_TIME_MS) {
1574 std::this_thread::sleep_for(std::chrono::milliseconds(lastUpdateTime + MONITOR_STEP_TIME_MS - currentTime));
1575 }
1576 }
1577 PRINT_HILOGI("jobMonitorList is empty, exit monitor");
1578 }
1579
UpdatePrintJobStateInJobParams(JobParameters * jobParams,uint32_t state,uint32_t subState)1580 void PrintCupsClient::UpdatePrintJobStateInJobParams(JobParameters *jobParams, uint32_t state, uint32_t subState)
1581 {
1582 if (jobParams != nullptr && jobParams->serviceAbility != nullptr) {
1583 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, state, subState);
1584 } else {
1585 PRINT_HILOGE("UpdatePrintJobStateInJobParams has nullptr parameter.");
1586 }
1587 }
1588
IfContinueToHandleJobState(std::shared_ptr<JobMonitorParam> monitorParams)1589 bool PrintCupsClient::IfContinueToHandleJobState(std::shared_ptr<JobMonitorParam> monitorParams)
1590 {
1591 if (monitorParams == nullptr) {
1592 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1593 return false;
1594 }
1595 if (monitorParams->isCanceled) {
1596 PRINT_HILOGI("cancel job and stop monitor it");
1597 if (!CancelPrinterJob(monitorParams->cupsJobId, monitorParams->printerName,
1598 monitorParams->jobOriginatingUserName)) {
1599 PRINT_HILOGE("cancel Job Error");
1600 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_COMPLETED,
1601 PRINT_JOB_COMPLETED_CANCELLED);
1602 return false;
1603 }
1604 }
1605 if (monitorParams->isInterrupt) {
1606 PRINT_HILOGI("Interrupt job and stop monitor it");
1607 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_BLOCKED,
1608 PRINT_JOB_BLOCKED_INTERRUPT);
1609 return false;
1610 }
1611 return QueryJobStateAndCallback(monitorParams);
1612 }
1613
QueryJobStateAndCallback(std::shared_ptr<JobMonitorParam> monitorParams)1614 bool PrintCupsClient::QueryJobStateAndCallback(std::shared_ptr<JobMonitorParam> monitorParams)
1615 {
1616 if (httpGetFd(monitorParams->http) < 0) {
1617 PRINT_HILOGE("http is nullptr");
1618 httpReconnect2(monitorParams->http, LONG_LONG_TIME_OUT, nullptr);
1619 }
1620 if (httpGetFd(monitorParams->http) < 0 || !CheckPrinterOnline(monitorParams)) {
1621 PRINT_HILOGE("unable connect to printer");
1622 if (monitorParams->serviceAbility == nullptr) {
1623 PRINT_HILOGE("serviceAbility is null");
1624 return false;
1625 }
1626 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_BLOCKED,
1627 PRINT_JOB_BLOCKED_OFFLINE);
1628 return true;
1629 }
1630 if (monitorParams->isFirstQueryState) {
1631 PRINT_HILOGD("skip first query state");
1632 monitorParams->isFirstQueryState = false;
1633 return true;
1634 }
1635 if (!QueryJobState(monitorParams->http, monitorParams)) {
1636 return true;
1637 }
1638 monitorParams->isPrinterStopped = IsPrinterStopped(monitorParams);
1639 ParseStateReasons(monitorParams);
1640 if (JobStatusCallback(monitorParams)) {
1641 PRINT_HILOGD("the job is processing");
1642 return true;
1643 }
1644 PRINT_HILOGI("the job is completed or canceled");
1645 return false;
1646 }
1647
IsPrinterStopped(std::shared_ptr<JobMonitorParam> monitorParams)1648 bool PrintCupsClient::IsPrinterStopped(std::shared_ptr<JobMonitorParam> monitorParams)
1649 {
1650 if (monitorParams == nullptr) {
1651 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1652 return false;
1653 }
1654 PrinterStatus printerStatus = PRINTER_STATUS_BUSY;
1655 bool isPrinterStatusAvailable = QueryPrinterStatusByUri(monitorParams->printerUri, printerStatus) == E_PRINT_NONE;
1656 PRINT_HILOGD("is printer status available: %{public}d, state:%{public}d",
1657 isPrinterStatusAvailable, printerStatus);
1658 if (isPrinterStatusAvailable && printerStatus == PRINTER_STATUS_UNAVAILABLE) {
1659 return true;
1660 }
1661 return false;
1662 }
1663
JobStatusCallback(std::shared_ptr<JobMonitorParam> monitorParams)1664 bool PrintCupsClient::JobStatusCallback(std::shared_ptr<JobMonitorParam> monitorParams)
1665 {
1666 if (monitorParams == nullptr) {
1667 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1668 return false;
1669 }
1670 PRINT_HILOGI("JOB %{public}d: %{public}s (%{public}s), PRINTER: %{public}s\n", monitorParams->cupsJobId,
1671 ippEnumString("job-state", (int)monitorParams->job_state), monitorParams->job_state_reasons,
1672 monitorParams->job_printer_state_reasons);
1673
1674 if (monitorParams->job_state == IPP_JOB_PROCESSING) {
1675 if (!monitorParams->isBlock) {
1676 PRINT_HILOGI("job is running");
1677 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId,
1678 PRINT_JOB_RUNNING, monitorParams->substate);
1679 return true;
1680 }
1681 PRINT_HILOGI("job is blocked");
1682 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId,
1683 PRINT_JOB_BLOCKED, monitorParams->substate);
1684 return true;
1685 }
1686
1687 if (monitorParams->job_state == IPP_JOB_PENDING || monitorParams->job_state == IPP_JOB_HELD) {
1688 PRINT_HILOGI("job is queued");
1689 if (monitorParams->job_state_reasons == JOB_STATE_REASON_PRINTER_STOP) {
1690 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_BLOCKED,
1691 PRINT_JOB_BLOCKED_PRINTER_UNAVAILABLE);
1692 return true;
1693 }
1694 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_QUEUED,
1695 PRINT_JOB_COMPLETED_SUCCESS);
1696 return true;
1697 }
1698
1699 if (monitorParams->job_state == IPP_JOB_STOPPED) {
1700 if (CancelPrinterJob(monitorParams->cupsJobId)) {
1701 PRINT_HILOGI("cancel PrinterJob because stopped");
1702 return true;
1703 }
1704 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_COMPLETED,
1705 GetNewSubstate(monitorParams->substate, PRINT_JOB_COMPLETED_CANCELLED));
1706 return false;
1707 }
1708 return SpecialJobStatusCallback(monitorParams);
1709 }
1710
SpecialJobStatusCallback(std::shared_ptr<JobMonitorParam> monitorParams)1711 bool PrintCupsClient::SpecialJobStatusCallback(std::shared_ptr<JobMonitorParam> monitorParams)
1712 {
1713 if (monitorParams == nullptr) {
1714 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1715 return false;
1716 }
1717
1718 if (monitorParams->job_state == IPP_JOB_COMPLETED) {
1719 if (!monitorParams->isBlock) {
1720 PRINT_HILOGI("job complete success");
1721 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId,
1722 PRINT_JOB_COMPLETED, PRINT_JOB_COMPLETED_SUCCESS);
1723 return false;
1724 }
1725 PRINT_HILOGI("job complete with error");
1726 if (monitorParams->timesOfSameState < STATE_UPDATE_STEP) {
1727 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId,
1728 PRINT_JOB_BLOCKED, monitorParams->substate);
1729 return true;
1730 }
1731 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId,
1732 PRINT_JOB_COMPLETED, PRINT_JOB_COMPLETED_SUCCESS);
1733 return false;
1734 }
1735
1736 // IPP_JOB_CANCELED or IPP_JOB_ABORTED
1737 if (!monitorParams->isBlock) {
1738 PRINT_HILOGI("job is canceled");
1739 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_COMPLETED,
1740 PRINT_JOB_COMPLETED_CANCELLED);
1741 return false;
1742 }
1743 PRINT_HILOGI("job cancel with error");
1744 if (monitorParams->timesOfSameState < STATE_UPDATE_STEP) {
1745 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId,
1746 PRINT_JOB_BLOCKED, monitorParams->substate);
1747 return true;
1748 }
1749 monitorParams->serviceAbility->UpdatePrintJobState(monitorParams->serviceJobId, PRINT_JOB_COMPLETED,
1750 PRINT_JOB_COMPLETED_CANCELLED);
1751 return false;
1752 }
1753
ParseStateReasons(std::shared_ptr<JobMonitorParam> monitorParams)1754 void PrintCupsClient::ParseStateReasons(std::shared_ptr<JobMonitorParam> monitorParams)
1755 {
1756 if (monitorParams == nullptr) {
1757 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1758 return;
1759 }
1760 monitorParams->isBlock = monitorParams->isPrinterStopped;
1761 monitorParams->substate = 0;
1762 int32_t index = 0;
1763 for (auto stateItem = FOLLOW_STATE_LIST.begin(); stateItem != FOLLOW_STATE_LIST.end(); stateItem++) {
1764 monitorParams->isBlock |= GetBlockedAndUpdateSubstate(monitorParams, monitorParams->policyArray[index],
1765 stateItem->first, stateItem->second);
1766 index++;
1767 }
1768 if (monitorParams->isBlock && monitorParams->substate == 0) {
1769 monitorParams->substate = GetNewSubstate(monitorParams->substate, PRINT_JOB_BLOCKED_UNKNOWN);
1770 }
1771 PRINT_HILOGI("state reasons parse result: isblocked(%{public}d), substate(%{public}d)",
1772 monitorParams->isBlock, monitorParams->substate);
1773 }
1774
GetBlockedAndUpdateSubstate(std::shared_ptr<JobMonitorParam> monitorParams,StatePolicy policy,std::string substateString,PrintJobSubState jobSubstate)1775 bool PrintCupsClient::GetBlockedAndUpdateSubstate(std::shared_ptr<JobMonitorParam> monitorParams, StatePolicy policy,
1776 std::string substateString, PrintJobSubState jobSubstate)
1777 {
1778 if (monitorParams == nullptr) {
1779 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1780 return true;
1781 }
1782 char* result = strstr(monitorParams->job_printer_state_reasons, substateString.c_str());
1783 if (result != nullptr) {
1784 PRINT_HILOGI("match %{public}s reason success", substateString.c_str());
1785 monitorParams->substate = GetNewSubstate(monitorParams->substate, jobSubstate);
1786 substateString.append(PRINTER_STATE_ERROR);
1787 if (strstr(monitorParams->job_printer_state_reasons, substateString.c_str()) != nullptr) {
1788 PRINT_HILOGD("error state reason");
1789 if (policy == STATE_POLICY_HINT) { return false; }
1790 if (policy == STATE_POLICY_DELAY && monitorParams->timesOfSameState == 0) { return false; }
1791 return true; // STATE_POLICY_STANDARD
1792 } else {
1793 PRINT_HILOGD("warning/report state reason");
1794 if (policy == STATE_POLICY_BLOCK) { return true; }
1795 return false; // STATE_POLICY_STANDARD
1796 }
1797 }
1798 return false;
1799 }
1800
GetNewSubstate(uint32_t substate,PrintJobSubState singleSubstate)1801 uint32_t PrintCupsClient::GetNewSubstate(uint32_t substate, PrintJobSubState singleSubstate)
1802 {
1803 PRINT_HILOGD("add new substate(%{public}d) to substate(%{public}d)", singleSubstate, substate);
1804 return substate * NUMBER_FOR_SPLICING_SUBSTATE + singleSubstate;
1805 }
1806
QueryJobState(http_t * http,std::shared_ptr<JobMonitorParam> monitorParams)1807 bool PrintCupsClient::QueryJobState(http_t *http, std::shared_ptr<JobMonitorParam> monitorParams)
1808 {
1809 ipp_t *request = nullptr; /* IPP request */
1810 ipp_t *response = nullptr; /* IPP response */
1811 int jattrsLen = 3;
1812 bool needUpdate = false;
1813 static const char * const jattrs[] = {
1814 "job-state",
1815 "job-state-reasons",
1816 "job-printer-state-reasons",
1817 };
1818 if (printAbility_ == nullptr) {
1819 PRINT_HILOGW("printAbility_ is null");
1820 return false;
1821 }
1822 if (http == nullptr || monitorParams == nullptr) {
1823 PRINT_HILOGE("QueryJobState monitorParams is null");
1824 return false;
1825 }
1826 if (monitorParams->cupsJobId > 0) {
1827 request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES);
1828 if (request == nullptr) {
1829 PRINT_HILOGE("Failed to create IPP request.");
1830 return false;
1831 }
1832 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr,
1833 monitorParams->printerUri.c_str());
1834 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", monitorParams->cupsJobId);
1835 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr,
1836 monitorParams->jobOriginatingUserName.c_str());
1837 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", jattrsLen, nullptr, jattrs);
1838 PRINT_HILOGD("get job state from cups service: start");
1839 response = printAbility_->DoRequest(http, request, "/");
1840 if (response == nullptr) {
1841 PRINT_HILOGE("Failed to get response from CUPS service.");
1842 ippDelete(request);
1843 return false;
1844 }
1845 needUpdate = UpdateJobState(monitorParams, response);
1846 ippDelete(response);
1847 }
1848 return needUpdate;
1849 }
1850
UpdateJobState(std::shared_ptr<JobMonitorParam> monitorParams,ipp_t * response)1851 bool PrintCupsClient::UpdateJobState(std::shared_ptr<JobMonitorParam> monitorParams, ipp_t *response)
1852 {
1853 if (monitorParams == nullptr) {
1854 PRINT_HILOGE("monitor job state failed, monitorParams is nullptr");
1855 return false;
1856 }
1857 ipp_attribute_t *attr = nullptr; /* Attribute in response */
1858 if (response == nullptr) {
1859 PRINT_HILOGE("Failed to get response from CUPS service.");
1860 return false;
1861 }
1862 ipp_jstate_t job_state = IPP_JOB_PENDING;
1863 char job_state_reasons[1024];
1864 char job_printer_state_reasons[1024];
1865 if ((attr = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != nullptr) {
1866 job_state = (ipp_jstate_t)ippGetInteger(attr, 0);
1867 }
1868 if ((attr = ippFindAttribute(response, "job-state-reasons", IPP_TAG_KEYWORD)) != nullptr) {
1869 ippAttributeString(attr, job_state_reasons, sizeof(job_state_reasons));
1870 }
1871 if ((attr = ippFindAttribute(response, "job-printer-state-reasons", IPP_TAG_KEYWORD)) != nullptr) {
1872 ippAttributeString(attr, job_printer_state_reasons, sizeof(job_printer_state_reasons));
1873 }
1874 if (monitorParams->job_state == job_state &&
1875 strcmp(monitorParams->job_printer_state_reasons, job_printer_state_reasons) == 0) {
1876 monitorParams->timesOfSameState++;
1877 if (monitorParams->timesOfSameState % STATE_UPDATE_STEP != 0) {
1878 PRINT_HILOGD("the prevous jobState is the same as current, ignore");
1879 return false;
1880 } else {
1881 return true;
1882 }
1883 }
1884 monitorParams->timesOfSameState = -1;
1885 monitorParams->job_state = job_state;
1886 strlcpy(monitorParams->job_state_reasons, job_state_reasons, sizeof(monitorParams->job_state_reasons));
1887 strlcpy(monitorParams->job_printer_state_reasons, job_printer_state_reasons,
1888 sizeof(monitorParams->job_printer_state_reasons));
1889 return true;
1890 }
1891
CheckPrinterOnline(std::shared_ptr<JobMonitorParam> monitorParams,const uint32_t timeout)1892 bool PrintCupsClient::CheckPrinterOnline(std::shared_ptr<JobMonitorParam> monitorParams, const uint32_t timeout)
1893 {
1894 http_t *http = nullptr;
1895 char scheme[32] = {0};
1896 char userpass[BUFFER_LEN] = {0};
1897 char host[BUFFER_LEN] = {0};
1898 char resource[BUFFER_LEN] = {0};
1899 int port = 0;
1900 if (monitorParams == nullptr) {
1901 PRINT_HILOGE("monitorParams is null");
1902 return false;
1903 }
1904 const char* printerUri = monitorParams->printerUri.c_str();
1905 const std::string printerId = monitorParams->printerId;
1906 PRINT_HILOGD("CheckPrinterOnline printerId: %{public}s", printerId.c_str());
1907 bool isUsbPrinter = monitorParams->printerUri.length() > USB_PRINTER.length() &&
1908 monitorParams->printerUri.substr(INDEX_ZERO, INDEX_THREE) == USB_PRINTER;
1909 bool isVendorPrinter = strstr(printerId.c_str(), VENDOR_PPD_DRIVER.c_str()) != nullptr;
1910 bool isCustomizedExtension = !(PrintUtil::startsWith(printerId, SPOOLER_BUNDLE_NAME) ||
1911 PrintUtil::startsWith(printerId, VENDOR_MANAGER_PREFIX));
1912 if ((isUsbPrinter || isCustomizedExtension || isVendorPrinter) && monitorParams->serviceAbility != nullptr) {
1913 if (monitorParams->serviceAbility->QueryDiscoveredPrinterInfoById(printerId) == nullptr) {
1914 PRINT_HILOGI("printer offline");
1915 return false;
1916 } else {
1917 PRINT_HILOGI("printer online");
1918 return true;
1919 }
1920 } else {
1921 httpSeparateURI(HTTP_URI_CODING_ALL, printerUri, scheme, sizeof(scheme),
1922 userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource));
1923 }
1924 if (host[0] == '\0') {
1925 PRINT_HILOGE("host is empty");
1926 return false;
1927 }
1928 std::string nic;
1929 if (IsIpConflict(printerId, nic)) {
1930 http = httpConnect3(host, port, nullptr, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, timeout, nullptr,
1931 nic.c_str());
1932 } else {
1933 http = httpConnect2(host, port, nullptr, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, timeout, nullptr);
1934 }
1935 if (http == nullptr) {
1936 PRINT_HILOGE("httpConnect2 printer failed");
1937 return false;
1938 }
1939 httpClose(http);
1940 return true;
1941 }
1942
ModifyCupsPrinterUri(const std::string & printerName,const std::string & printerUri)1943 bool PrintCupsClient::ModifyCupsPrinterUri(const std::string &printerName, const std::string &printerUri)
1944 {
1945 PRINT_HILOGI("ModifyCupsPrinterUri enter");
1946 if (printAbility_ == nullptr) {
1947 PRINT_HILOGW("printAbility_ is null");
1948 return false;
1949 }
1950 cups_dest_t *dest = printAbility_->GetNamedDest(CUPS_HTTP_DEFAULT, printerName.c_str(), nullptr);
1951 if (dest == nullptr) {
1952 PRINT_HILOGW("failed to find printer");
1953 return false;
1954 }
1955 std::string standardUri = printerUri;
1956 const char *makeModel = cupsGetOption("printer-make-and-model", dest->num_options, dest->options);
1957 if (makeModel != nullptr) {
1958 PRINT_HILOGD("makeModel=%{public}s", makeModel);
1959 if (strstr(makeModel, BSUNI_PPD_NAME.c_str()) != nullptr) {
1960 standardUri = StandardizePrinterUri(printerUri, BSUNI_PPD_NAME);
1961 }
1962 }
1963 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
1964 dest = nullptr;
1965
1966 ipp_t *request = nullptr;
1967 char uri[HTTP_MAX_URI] = {0};
1968 ippSetPort(CUPS_SEVER_PORT);
1969 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
1970 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", nullptr, "localhost", 0, "/printers/%s",
1971 printerName.c_str());
1972 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, uri);
1973 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, cupsUser());
1974 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", nullptr, standardUri.c_str());
1975 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
1976 printAbility_->FreeRequest(printAbility_->DoRequest(nullptr, request, "/admin/"));
1977 if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE) {
1978 PRINT_HILOGE("modify printer error: %{public}s", cupsLastErrorString());
1979 return false;
1980 }
1981 PRINT_HILOGI("modify printer success");
1982 return true;
1983 }
1984
CancelCupsJob(std::string serviceJobId)1985 void PrintCupsClient::CancelCupsJob(std::string serviceJobId)
1986 {
1987 PRINT_HILOGD("CancelCupsJob(): Enter, serviceJobId: %{public}s", serviceJobId.c_str());
1988 int jobIndex = -1;
1989 for (int index = 0; index < static_cast<int>(jobQueue_.size()); index++) {
1990 PRINT_HILOGD("jobQueue_[index]->serviceJobId: %{public}s", jobQueue_[index]->serviceJobId.c_str());
1991 if (jobQueue_[index]->serviceJobId == serviceJobId) {
1992 jobIndex = index;
1993 break;
1994 }
1995 }
1996 PRINT_HILOGI("jobIndex: %{public}d", jobIndex);
1997 if (jobIndex >= 0) {
1998 PRINT_HILOGI("job in queue, delete");
1999 JobParameters* erasedJob = jobQueue_.at(jobIndex);
2000 if (erasedJob != nullptr) {
2001 delete erasedJob;
2002 }
2003 jobQueue_.erase(jobQueue_.begin() + jobIndex);
2004 PrintServiceAbility::GetInstance()->UpdatePrintJobState(serviceJobId, PRINT_JOB_COMPLETED,
2005 PRINT_JOB_COMPLETED_CANCELLED);
2006 } else {
2007 // job is processing
2008 if (currentJob_ != nullptr && currentJob_->serviceJobId == serviceJobId) { currentJob_->isCanceled = true; }
2009 std::lock_guard<std::mutex> lock(jobMonitorMutex_);
2010 auto cmp = [serviceJobId](std::shared_ptr<JobMonitorParam> monitorParams) {
2011 return (monitorParams != nullptr && monitorParams->serviceJobId == serviceJobId);
2012 };
2013 auto monitorItem = std::find_if(jobMonitorList_.begin(), jobMonitorList_.end(), cmp);
2014 if (monitorItem == jobMonitorList_.end()) {
2015 PRINT_HILOGW("job is not exist");
2016 PrintServiceAbility::GetInstance()->UpdatePrintJobState(serviceJobId, PRINT_JOB_COMPLETED,
2017 PRINT_JOB_COMPLETED_CANCELLED);
2018 return;
2019 }
2020 auto canceledMonitor = *monitorItem;
2021 canceledMonitor->isCanceled = true;
2022 }
2023 }
2024
InterruptCupsJob(std::string serviceJobId)2025 void PrintCupsClient::InterruptCupsJob(std::string serviceJobId)
2026 {
2027 PRINT_HILOGD("InterruptCupsJob(): Enter, serviceJobId: %{public}s", serviceJobId.c_str());
2028 int jobIndex = -1;
2029 for (int index = 0; index < static_cast<int>(jobQueue_.size()); index++) {
2030 PRINT_HILOGD("jobQueue_[index]->serviceJobId: %{public}s", jobQueue_[index]->serviceJobId.c_str());
2031 if (jobQueue_[index]->serviceJobId == serviceJobId) {
2032 jobIndex = index;
2033 break;
2034 }
2035 }
2036 PRINT_HILOGI("jobIndex: %{public}d", jobIndex);
2037 if (jobIndex >= 0) {
2038 PRINT_HILOGI("job in queue, delete");
2039 JobParameters* erasedJob = jobQueue_.at(jobIndex);
2040 if (erasedJob != nullptr) {
2041 delete erasedJob;
2042 }
2043 jobQueue_.erase(jobQueue_.begin() + jobIndex);
2044 PrintServiceAbility::GetInstance()->UpdatePrintJobState(serviceJobId, PRINT_JOB_BLOCKED,
2045 PRINT_JOB_BLOCKED_INTERRUPT);
2046 } else {
2047 // job is processing
2048 if (currentJob_ != nullptr && currentJob_->serviceJobId == serviceJobId) {
2049 currentJob_->isCanceled = true;
2050 }
2051 std::lock_guard<std::mutex> lock(jobMonitorMutex_);
2052 auto cmp = [serviceJobId](std::shared_ptr<JobMonitorParam> monitorParams) {
2053 return (monitorParams != nullptr && monitorParams->serviceJobId == serviceJobId);
2054 };
2055 auto monitorItem = std::find_if(jobMonitorList_.begin(), jobMonitorList_.end(), cmp);
2056 if (monitorItem == jobMonitorList_.end()) {
2057 PRINT_HILOGW("job is not exist");
2058 return;
2059 }
2060 auto interruptMonitor = *monitorItem;
2061 if (!CancelPrinterJob(interruptMonitor->cupsJobId, interruptMonitor->printerName,
2062 interruptMonitor->jobOriginatingUserName)) {
2063 PRINT_HILOGE("cancel Job Error");
2064 }
2065 interruptMonitor->isInterrupt = true;
2066 }
2067 }
2068
UpdateJobParameterByBoolOption(Json::Value & optionJson,JobParameters * params)2069 void PrintCupsClient::UpdateJobParameterByBoolOption(Json::Value& optionJson, JobParameters *params)
2070 {
2071 if (optionJson.isMember("isBorderless") && optionJson["isBorderless"].isBool()) {
2072 bool isBorderless = optionJson["isBorderless"].asBool();
2073 params->borderless = isBorderless ? TRUE : FALSE;
2074 } else {
2075 params->borderless = TRUE;
2076 }
2077
2078 if (optionJson.isMember("isAutoRotate") && optionJson["isAutoRotate"].isBool()) {
2079 params->isAutoRotate = optionJson["isAutoRotate"].asBool();
2080 } else {
2081 // default autoRotate if option dont't contains it
2082 params->isAutoRotate = true;
2083 }
2084
2085 if (optionJson.isMember("isReverse") && optionJson["isReverse"].isBool()) {
2086 params->isReverse = optionJson["isReverse"].asBool();
2087 } else {
2088 params->isReverse = false;
2089 }
2090
2091 if (optionJson.isMember("isCollate") && optionJson["isCollate"].isBool()) {
2092 params->isCollate = optionJson["isCollate"].asBool();
2093 } else {
2094 params->isCollate = true;
2095 }
2096 }
2097
UpdateJobParameterByOption(Json::Value & optionJson,JobParameters * params)2098 void PrintCupsClient::UpdateJobParameterByOption(Json::Value& optionJson, JobParameters *params)
2099 {
2100 if (optionJson.isMember("cupsOptions") && optionJson["cupsOptions"].isString()) {
2101 params->printerAttrsOptionCupsOption = optionJson["cupsOptions"].asString();
2102 }
2103
2104 if (optionJson.isMember("printQuality") && optionJson["printQuality"].isString()) {
2105 params->printQuality = optionJson["printQuality"].asString();
2106 } else {
2107 params->printQuality = CUPS_PRINT_QUALITY_NORMAL;
2108 }
2109
2110 if (optionJson.isMember("jobName") && optionJson["jobName"].isString()) {
2111 params->jobName = optionJson["jobName"].asString();
2112 } else {
2113 params->jobName = DEFAULT_JOB_NAME;
2114 }
2115
2116 if (optionJson.isMember("mediaType") && optionJson["mediaType"].isString()) {
2117 params->mediaType = optionJson["mediaType"].asString();
2118 } else {
2119 params->mediaType = CUPS_MEDIA_TYPE_PLAIN;
2120 }
2121
2122 UpdateJobParameterByBoolOption(optionJson, params);
2123
2124 if (PrintJsonUtil::IsMember(optionJson, "advancedOptions") && optionJson["advancedOptions"].isObject()) {
2125 params->advancedOpsJson = optionJson["advancedOptions"];
2126 }
2127 }
2128
BuildJobParameters(const PrintJob & jobInfo,const std::string & userName)2129 JobParameters* PrintCupsClient::BuildJobParameters(const PrintJob &jobInfo, const std::string &userName)
2130 {
2131 JobParameters *params = nullptr;
2132 if (!jobInfo.HasOption()) {
2133 PRINT_HILOGE("option is empty");
2134 return params;
2135 }
2136 std::string option = jobInfo.GetOption();
2137 Json::Value optionJson;
2138 if (!PrintJsonUtil::Parse(option, optionJson)) {
2139 PRINT_HILOGE("option can not parse to json object");
2140 return params;
2141 }
2142 PRINT_HILOGD("test optionJson: %{private}s", (PrintJsonUtil::WriteString(optionJson)).c_str());
2143 if (!PrintJsonUtil::IsMember(optionJson, "printerUri") || !optionJson["printerUri"].isString() ||
2144 !PrintJsonUtil::IsMember(optionJson, "printerName") || !optionJson["printerName"].isString() ||
2145 !PrintJsonUtil::IsMember(optionJson, "documentFormat") || !optionJson["documentFormat"].isString()) {
2146 PRINT_HILOGE("The option does not have a necessary attribute.");
2147 return params;
2148 }
2149 params = new (std::nothrow) JobParameters {};
2150 if (params == nullptr) {
2151 PRINT_HILOGE("new JobParameters returns nullptr");
2152 return params;
2153 }
2154 jobInfo.DupFdList(params->fdList);
2155 params->serviceJobId = jobInfo.GetJobId();
2156 params->numCopies = jobInfo.GetCopyNumber();
2157 params->duplex = GetDulpexString(jobInfo.GetDuplexMode());
2158 params->jobOriginatingUserName = userName;
2159 params->mediaSize = GetMedieSize(jobInfo);
2160 params->color = GetColorString(jobInfo.GetColorMode());
2161 params->printerId = jobInfo.GetPrinterId();
2162 params->printerName = PrintUtil::StandardizePrinterName(optionJson["printerName"].asString());
2163 params->printerUri = optionJson["printerUri"].asString();
2164 params->documentFormat = optionJson["documentFormat"].asString();
2165 params->isLandscape = jobInfo.GetIsLandscape();
2166 UpdateJobParameterByOption(optionJson, params);
2167 params->serviceAbility = PrintServiceAbility::GetInstance();
2168 return params;
2169 }
2170
DumpJobParameters(JobParameters * jobParams)2171 void PrintCupsClient::DumpJobParameters(JobParameters* jobParams)
2172 {
2173 if (jobParams == nullptr) {
2174 PRINT_HILOGE("DumpJobParameters fail.");
2175 return;
2176 }
2177 PRINT_HILOGD("jobParams->serviceJobId: %{public}s", jobParams->serviceJobId.c_str());
2178 PRINT_HILOGD("jobParams->borderless: %{public}d", jobParams->borderless);
2179 PRINT_HILOGD("jobParams->numCopies: %{public}d", jobParams->numCopies);
2180 PRINT_HILOGD("jobParams->duplex: %{public}s", jobParams->duplex.c_str());
2181 PRINT_HILOGD("jobParams->printQuality: %{public}s", jobParams->printQuality.c_str());
2182 PRINT_HILOGD("jobParams->jobName: %{public}s", jobParams->jobName.c_str());
2183 PRINT_HILOGD("jobParams->jobOriginatingUserName: %{public}s", jobParams->jobOriginatingUserName.c_str());
2184 PRINT_HILOGD("jobParams->printerId: %{private}s", jobParams->printerId.c_str());
2185 PRINT_HILOGD("jobParams->printerName: %{private}s", jobParams->printerName.c_str());
2186 PRINT_HILOGD("jobParams->printerUri: %{private}s", jobParams->printerUri.c_str());
2187 PRINT_HILOGD("jobParams->documentFormat: %{public}s", jobParams->documentFormat.c_str());
2188 PRINT_HILOGD("jobParams->mediaSize: %{public}s", jobParams->mediaSize.c_str());
2189 PRINT_HILOGD("jobParams->mediaType: %{public}s", jobParams->mediaType.c_str());
2190 PRINT_HILOGD("jobParams->color: %{public}s", jobParams->color.c_str());
2191 PRINT_HILOGD("jobParams->isLandscape: %{public}d", jobParams->isLandscape);
2192 PRINT_HILOGD("jobParams->isAutoRotate: %{public}d", jobParams->isAutoRotate);
2193 PRINT_HILOGD("jobParams->isReverse: %{public}d", jobParams->isReverse);
2194 PRINT_HILOGD("jobParams->isCollate: %{public}d", jobParams->isCollate);
2195 PRINT_HILOGD("jobParams->printerAttrsOptionCupsOption: %{public}s",
2196 jobParams->printerAttrsOptionCupsOption.c_str());
2197 }
2198
2199
GetMedieSize(const PrintJob & jobInfo)2200 std::string PrintCupsClient::GetMedieSize(const PrintJob &jobInfo)
2201 {
2202 PrintPageSize pageSize;
2203 jobInfo.GetPageSize(pageSize);
2204 return pageSize.GetName();
2205 }
2206
GetDulpexString(uint32_t duplexCode)2207 std::string PrintCupsClient::GetDulpexString(uint32_t duplexCode)
2208 {
2209 DuplexModeCode duplex = static_cast<DuplexModeCode>(duplexCode);
2210 switch (duplex) {
2211 case DUPLEX_MODE_ONE_SIDED:
2212 return CUPS_SIDES_ONE_SIDED;
2213 case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
2214 return CUPS_SIDES_TWO_SIDED_PORTRAIT;
2215 case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
2216 return CUPS_SIDES_TWO_SIDED_LANDSCAPE;
2217 default:
2218 return CUPS_SIDES_ONE_SIDED;
2219 }
2220 }
2221
GetColorString(uint32_t colorCode)2222 std::string PrintCupsClient::GetColorString(uint32_t colorCode)
2223 {
2224 ColorModeCode color = static_cast<ColorModeCode>(colorCode);
2225 switch (color) {
2226 case COLOR_MODE_MONOCHROME:
2227 return CUPS_PRINT_COLOR_MODE_MONOCHROME;
2228 case COLOR_MODE_COLOR:
2229 return CUPS_PRINT_COLOR_MODE_COLOR;
2230 default:
2231 return CUPS_PRINT_COLOR_MODE_AUTO;
2232 }
2233 }
2234
IsCupsServerAlive()2235 bool PrintCupsClient::IsCupsServerAlive()
2236 {
2237 http_t *http = nullptr;
2238 ippSetPort(CUPS_SEVER_PORT);
2239 http = httpConnect2(cupsServer(), ippPort(), nullptr, AF_UNSPEC,
2240 HTTP_ENCRYPTION_IF_REQUESTED, 1, LONG_TIME_OUT, nullptr);
2241 if (http == nullptr) {
2242 PRINT_HILOGE("cups server is not alive");
2243 return false;
2244 }
2245 httpClose(http);
2246 return true;
2247 }
2248
2249 /**
2250 * @brief check printer is exist
2251 * @param printerName printer name
2252 * @return true printer exist
2253 * @return false printer is not exist
2254 */
IsPrinterExist(const char * printerUri,const char * standardPrinterName,const char * ppdName)2255 bool PrintCupsClient::IsPrinterExist(const char *printerUri, const char *standardPrinterName, const char *ppdName)
2256 {
2257 bool printerExist = false;
2258 cups_dest_t *dest;
2259 PRINT_HILOGD("IsPrinterExist enter");
2260 if (printAbility_ == nullptr) {
2261 PRINT_HILOGW("printAbility_ is null");
2262 return printerExist;
2263 }
2264 dest = printAbility_->GetNamedDest(CUPS_HTTP_DEFAULT, standardPrinterName, nullptr);
2265 if (dest != nullptr) {
2266 const char *deviceUri = cupsGetOption("device-uri", dest->num_options, dest->options);
2267 if (deviceUri == nullptr) {
2268 PRINT_HILOGD("deviceUri is null");
2269 return false;
2270 }
2271 PRINT_HILOGD("deviceUri=%{private}s", deviceUri);
2272 const char *makeModel = cupsGetOption("printer-make-and-model", dest->num_options, dest->options);
2273 if (makeModel == nullptr) {
2274 PRINT_HILOGD("makeModel is null");
2275 return false;
2276 }
2277 PRINT_HILOGD("makeModel=%{private}s", makeModel);
2278 int printerState = cupsGetIntegerOption("printer-state", dest->num_options, dest->options);
2279 PRINT_HILOGD("printerState=%{private}d", printerState);
2280 if (printerState == IPP_PRINTER_STOPPED || makeModel == nullptr || strcmp(deviceUri, printerUri) != 0) {
2281 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
2282 PRINT_HILOGI("Printer information needs to be modified");
2283 return printerExist;
2284 }
2285 if (strcmp(ppdName, DEFAULT_PPD_NAME.c_str()) == 0) {
2286 // find everywhere or remote printr driver
2287 printerExist = (strstr(makeModel, DEFAULT_MAKE_MODEL.c_str()) != nullptr) ||
2288 (strstr(makeModel, REMOTE_PRINTER_MAKE_MODEL.c_str()) != nullptr);
2289 } else if (strcmp(ppdName, BSUNI_PPD_NAME.c_str()) == 0) {
2290 printerExist = (strstr(makeModel, BSUNI_PPD_NAME.c_str()) != nullptr);
2291 } else {
2292 // vendor ppd need to be checked
2293 if (!PrintServiceAbility::GetInstance()->IsPrinterPpdUpdateRequired(standardPrinterName,
2294 GetPpdHashCode(ppdName))) {
2295 printerExist = true;
2296 PRINT_HILOGD("no need to update ppd");
2297 }
2298 }
2299 printAbility_->FreeDests(FREE_ONE_PRINTER, dest);
2300 }
2301 return printerExist;
2302 }
2303
ConvertInchTo100MM(float num)2304 float PrintCupsClient::ConvertInchTo100MM(float num)
2305 {
2306 return ((num / THOUSAND_INCH) * CONVERSION_UNIT);
2307 }
2308
IsIpConflict(const std::string & printerId,std::string & nic)2309 bool PrintCupsClient::IsIpConflict(const std::string &printerId, std::string &nic) __attribute__((no_sanitize("cfi")))
2310 {
2311 if (printerId.find(P2P_PRINTER) == std::string::npos) {
2312 PRINT_HILOGD("The printer is not p2p: %{private}s", printerId.c_str());
2313 return false;
2314 }
2315 bool isWifiConnected = false;
2316 auto wifiDevice = Wifi::WifiDevice::GetInstance(OHOS::WIFI_DEVICE_SYS_ABILITY_ID);
2317 if (!wifiDevice) {
2318 PRINT_HILOGE("wifiDevice GetInstance failed.");
2319 return false;
2320 }
2321 wifiDevice->IsConnected(isWifiConnected);
2322 PRINT_HILOGD("isWifiConnected: %{public}d", isWifiConnected);
2323 Wifi::WifiP2pLinkedInfo p2pLinkedInfo;
2324 Wifi::WifiP2p::GetInstance(OHOS::WIFI_P2P_SYS_ABILITY_ID)->QueryP2pLinkedInfo(p2pLinkedInfo);
2325 PRINT_HILOGD("P2pConnectedState: %{public}d", p2pLinkedInfo.GetConnectState());
2326 if (isWifiConnected && p2pLinkedInfo.GetConnectState() == Wifi::P2pConnectedState::P2P_CONNECTED) {
2327 Wifi::IpInfo info;
2328 auto wifiDevice = Wifi::WifiDevice::GetInstance(OHOS::WIFI_DEVICE_SYS_ABILITY_ID);
2329 if (!wifiDevice) {
2330 PRINT_HILOGE("wifiDevice GetInstance failed.");
2331 return false;
2332 }
2333 wifiDevice->GetIpInfo(info);
2334 PRINT_HILOGD("wifi server ip: %{private}s", GetIpAddress(info.serverIp).c_str());
2335 PRINT_HILOGD("p2p go ip: %{private}s", p2pLinkedInfo.GetGroupOwnerAddress().c_str());
2336 if (GetIpAddress(info.serverIp) == p2pLinkedInfo.GetGroupOwnerAddress()) {
2337 Wifi::WifiP2pGroupInfo group;
2338 Wifi::WifiP2p::GetInstance(OHOS::WIFI_P2P_SYS_ABILITY_ID)->GetCurrentGroup(group);
2339 nic = group.GetInterface();
2340 PRINT_HILOGI("The P2P ip conflicts with the wlan ip, p2p nic: %{public}s", nic.c_str());
2341 return true;
2342 }
2343 }
2344 return false;
2345 }
2346
GetIpAddress(unsigned int number)2347 std::string PrintCupsClient::GetIpAddress(unsigned int number)
2348 {
2349 unsigned int ip3 = (number << IP_RIGHT_SHIFT_0) >> IP_RIGHT_SHIFT_24;
2350 unsigned int ip2 = (number << IP_RIGHT_SHIFT_8) >> IP_RIGHT_SHIFT_24;
2351 unsigned int ip1 = (number << IP_RIGHT_SHIFT_16) >> IP_RIGHT_SHIFT_24;
2352 unsigned int ip0 = (number << IP_RIGHT_SHIFT_24) >> IP_RIGHT_SHIFT_24;
2353 return std::to_string(ip3) + "." + std::to_string(ip2) + "." + std::to_string(ip1) + "." + std::to_string(ip0);
2354 }
2355
DiscoverUsbPrinters(std::vector<PrinterInfo> & printers)2356 int32_t PrintCupsClient::DiscoverUsbPrinters(std::vector<PrinterInfo> &printers)
2357 {
2358 int longStatus = 0;
2359 const char* include_schemes = CUPS_INCLUDE_ALL;
2360 const char* exclude_schemes = CUPS_EXCLUDE_NONE;
2361 int timeout = CUPS_TIMEOUT_DEFAULT;
2362 PRINT_HILOGD("DiscoverUsbPrinters cupsGetDevices");
2363 ClearUsbPrinters();
2364 if (cupsGetDevices(CUPS_HTTP_DEFAULT, timeout, include_schemes, exclude_schemes,
2365 DeviceCb, &longStatus) != IPP_OK) {
2366 PRINT_HILOGE("lpinfo error : %{public}s", cupsLastErrorString());
2367 return E_PRINT_SERVER_FAILURE;
2368 }
2369 printers = GetUsbPrinters();
2370 return E_PRINT_NONE;
2371 }
2372
DiscoverBackendPrinters(std::vector<PrinterInfo> & printers)2373 int32_t PrintCupsClient::DiscoverBackendPrinters(std::vector<PrinterInfo> &printers)
2374 {
2375 int longStatus = 0;
2376 const char* include_schemes = CUPS_INCLUDE_ALL;
2377 const char* exclude_schemes = CUPS_EXCLUDE_NONE;
2378 int timeout = CUPS_TIMEOUT_DEFAULT;
2379 PRINT_HILOGD("DiscoverBackendPrinters cupsGetDevices");
2380 ClearBackendPrinters();
2381 if (cupsGetDevices(CUPS_HTTP_DEFAULT, timeout, include_schemes, exclude_schemes,
2382 DeviceCb, &longStatus) != IPP_OK) {
2383 PRINT_HILOGE("lpinfo error : %{public}s", cupsLastErrorString());
2384 return E_PRINT_SERVER_FAILURE;
2385 }
2386 printers = GetBackendPrinters();
2387 return E_PRINT_NONE;
2388 }
2389
ResumePrinter(const std::string & printerName)2390 bool PrintCupsClient::ResumePrinter(const std::string &printerName)
2391 {
2392 if (printAbility_ == nullptr) {
2393 PRINT_HILOGE("printAbility is null");
2394 return false;
2395 }
2396 ipp_t *request = nullptr;
2397 char uri[HTTP_MAX_URI] = {0};
2398 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", nullptr, "localhost", 0, "/printers/%s",
2399 printerName.c_str());
2400 request = ippNewRequest(IPP_OP_RESUME_PRINTER);
2401 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, uri);
2402 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, cupsUser());
2403 PRINT_HILOGD("IPP_OP_RESUME_PRINTER cupsDoRequest");
2404 ippDelete(printAbility_->DoRequest(nullptr, request, "/admin/"));
2405 if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE) {
2406 PRINT_HILOGE("resume printer error: %{public}s", cupsLastErrorString());
2407 return false;
2408 }
2409 PRINT_HILOGI("resume printer success");
2410 return true;
2411 }
2412
CancelPrinterJob(int cupsJobId)2413 bool PrintCupsClient::CancelPrinterJob(int cupsJobId)
2414 {
2415 char job_uri[1024];
2416 httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", nullptr,
2417 "localhost", 0, "/jobs/%d", cupsJobId);
2418 PRINT_HILOGE("cancel job_uri: %s", job_uri);
2419 ipp_t *cancel_request = ippNewRequest(IPP_OP_CANCEL_JOB);
2420 ippAddString(cancel_request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", nullptr, job_uri);
2421 ippDelete(printAbility_->DoRequest(nullptr, cancel_request, "/admin/"));
2422 if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE) {
2423 PRINT_HILOGE("cancel printJob error: %{public}s", cupsLastErrorString());
2424 return false;
2425 }
2426 PRINT_HILOGI("cancel printJob success");
2427 return true;
2428 }
2429
CancelPrinterJob(int cupsJobId,const std::string & name,const std::string & user)2430 bool PrintCupsClient::CancelPrinterJob(int cupsJobId, const std::string &name, const std::string &user)
2431 {
2432 ipp_t *request = ippNewRequest(IPP_OP_CANCEL_JOB);
2433 char uri[HTTP_MAX_URI] = {0};
2434 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s",
2435 name.c_str());
2436 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
2437 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", cupsJobId);
2438 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user.c_str());
2439 ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs/"));
2440 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
2441 PRINT_HILOGW("Cancel of job %{public}d failed: %{public}s", cupsJobId, cupsLastErrorString());
2442 return false;
2443 } else {
2444 PRINT_HILOGI("Job %{public}d canceled", cupsJobId);
2445 return true;
2446 }
2447 }
2448
IsIpAddress(const char * host)2449 bool PrintCupsClient::IsIpAddress(const char* host)
2450 {
2451 if (host == NULL) {
2452 PRINT_HILOGW("host is null");
2453 return false;
2454 }
2455 struct in_addr addr4;
2456 struct in6_addr addr6;
2457 if ((inet_pton(AF_INET, host, &addr4) == 1) ||
2458 (inet_pton(AF_INET6, host, &addr6) == 1)) {
2459 return true;
2460 } else {
2461 PRINT_HILOGW("not ipv4 or ipv6");
2462 return false;
2463 }
2464 }
2465
GetPpdHashCode(const std::string & ppdName)2466 std::string PrintCupsClient::GetPpdHashCode(const std::string& ppdName)
2467 {
2468 std::string ppdFilePath = GetCurCupsRootDir() + "/datadir/model/" + ppdName;
2469
2470 std::ifstream file(ppdFilePath, std::ios::binary | std::ios::ate);
2471 if (!file.is_open()) {
2472 PRINT_HILOGE("ppd %{private}s open failed", ppdName.c_str());
2473 return "";
2474 }
2475
2476 std::streamsize size = file.tellg();
2477 file.seekg(0, std::ios::beg);
2478
2479 std::vector<char> buffer(size);
2480 if (!file.read(buffer.data(), size)) {
2481 PRINT_HILOGE("ppd %{private}s read failed", ppdName.c_str());
2482 return "";
2483 }
2484
2485 int32_t HASH_BUFFER_SIZE = 32;
2486 unsigned char hash[HASH_BUFFER_SIZE];
2487 size_t hashSize = sizeof(hash);
2488
2489 const char* HASH_ALGORITHM = "sha2-256";
2490 ssize_t result = cupsHashData(HASH_ALGORITHM, buffer.data(), size, hash, hashSize);
2491 if (result <= 0) {
2492 PRINT_HILOGE("cupsHashData fail, ret = %{public}d", result);
2493 return "";
2494 }
2495
2496 std::ostringstream oss;
2497 constexpr int32_t HEX_STRING_WIDTH = 2;
2498 oss << std::hex << std::setfill('0');
2499 for (int i = 0; i < result; ++i) {
2500 oss << std::setw(HEX_STRING_WIDTH) << static_cast<unsigned>(hash[i]);
2501 }
2502 return oss.str();
2503 }
2504
2505 }