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