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