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 <string>
19 #include <cups/cups-private.h>
20 #include <thread>
21 #include <semaphore.h>
22 #include <csignal>
23 #include <cstdlib>
24 #include <dirent.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <wifi_device.h>
28 #include <wifi_p2p.h>
29 #include <wifi_p2p_msg.h>
30
31 #include "system_ability_definition.h"
32 #include "parameter.h"
33 #include "nlohmann/json.hpp"
34 #include "print_service_ability.h"
35 #include "print_log.h"
36 #include "print_constant.h"
37 #include "print_utils.h"
38 #include "print_service_converter.h"
39 #include "print_cups_attribute.h"
40
41 namespace OHOS::Print {
42 using namespace std;
43 using json = nlohmann::json;
44
45 const uint32_t THOUSAND_INCH = 1000;
46 const uint32_t CUPS_SEVER_PORT = 1631;
47 const uint32_t TIME_OUT = 2000;
48 const uint32_t CONVERSION_UNIT = 2540;
49 const uint32_t LONG_TIME_OUT = 3000;
50 const uint32_t LONG_LONG_TIME_OUT = 30000;
51 const uint32_t INTERVAL_FOR_FIRST_QUERY = 1;
52 const uint32_t INTERVAL_FOR_QUERY = 2;
53 const uint32_t OFFLINE_RETRY_TIMES = 1;
54 const uint32_t RESOURCE_COUNT = 2;
55 const uint32_t DIR_COUNT = 3;
56 const uint32_t INDEX_ZERO = 0;
57 const uint32_t INDEX_ONE = 1;
58 const uint32_t INDEX_TWO = 2;
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
68 static bool g_isFirstQueryState = false;
69
70 static const std::string CUPS_ROOT_DIR = "/data/service/el1/public/print_service/cups";
71 static const std::string CUPS_RUN_DIR = "/data/service/el1/public/print_service/cups/run";
72 static const std::string DEFAULT_PPD_NAME = "everywhere";
73 static const std::string DEFAULT_MAKE_MODEL = "IPP Everywhere";
74 static const std::string DEFAULT_USER = "default";
75 static const std::string PRINTER_STATE_WAITING_COMPLETE = "cups-waiting-for-job-completed";
76 static const std::string PRINTER_STATE_WIFI_NOT_CONFIGURED = "wifi-not-configured-report";
77 static const std::string PRINTER_STATE_IGNORE_HP = "wifi-not-configured-report,cups-waiting-for-job-completed";
78 static const std::string PRINTER_STATE_IGNORE_BUSY =
79 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-history,cups-waiting-for-job-completed";
80 static const std::string PRINTER_STATE_IGNORE_BUSY_COMPLETED =
81 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-history";
82 static const std::string PRINTER_STATE_IGNORE_BUSY_MISSING_JOB_STATE =
83 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-state";
84 static const std::string PRINTER_STATE_IGNORE_BUSY_MISSING_JOB_STATE_COMPLETED =
85 "cups-ipp-conformance-failure-report,cups-ipp-missing-job-state,cups-waiting-for-job-completed";
86 static const std::string PRINTER_STATE_IGNORE_BUSY_WAITING_COMPLETE_OTHER_REPORT =
87 "cups-waiting-for-job-completed,other-report";
88 static const std::string PRINTER_STATE_IGNORE_BUSY_OTHER_REPORT = "other-report";
89 static const std::string PRINTER_STATE_NONE = "none";
90 static const std::string PRINTER_STATE_EMPTY = "";
91 static const std::string PRINTER_STATE_MEDIA_EMPTY = "media-empty";
92 static const std::string PRINTER_STATE_MEDIA_JAM = "media-jam";
93 static const std::string PRINTER_STATE_PAUSED = "paused";
94 static const std::string PRINTER_STATE_TONER_LOW = "toner-low";
95 static const std::string PRINTER_STATE_TONER_EMPTY = "toner-empty";
96 static const std::string PRINTER_STATE_DOOR_EMPTY = "door-open";
97 static const std::string PRINTER_STATE_MEDIA_NEEDED = "media-needed";
98 static const std::string PRINTER_STATE_MARKER_LOW = "marker-supply-low";
99 static const std::string PRINTER_STATE_MARKER_EMPTY = "marker-supply-empty";
100 static const std::string PRINTER_STATE_INK_EMPTY = "marker-ink-almost-empty";
101 static const std::string PRINTER_STATE_COVER_OPEN = "cover-open";
102 static const std::string PRINTER_STATE_OFFLINE = "offline";
103 static const std::string DEFAULT_JOB_NAME = "test";
104 static const std::string CUPSD_CONTROL_PARAM = "print.cupsd.ready";
105 static const std::string P2P_PRINTER = "p2p";
106 static const std::vector<std::string> IGNORE_STATE_LIST = {PRINTER_STATE_WAITING_COMPLETE,
107 PRINTER_STATE_NONE,
108 PRINTER_STATE_EMPTY,
109 PRINTER_STATE_WIFI_NOT_CONFIGURED,
110 PRINTER_STATE_IGNORE_HP,
111 PRINTER_STATE_IGNORE_BUSY,
112 PRINTER_STATE_IGNORE_BUSY_COMPLETED,
113 PRINTER_STATE_IGNORE_BUSY_MISSING_JOB_STATE,
114 PRINTER_STATE_IGNORE_BUSY_MISSING_JOB_STATE_COMPLETED,
115 PRINTER_STATE_IGNORE_BUSY_WAITING_COMPLETE_OTHER_REPORT,
116 PRINTER_STATE_IGNORE_BUSY_OTHER_REPORT};
117
PrintCupsClient()118 PrintCupsClient::PrintCupsClient()
119 {}
120
~PrintCupsClient()121 PrintCupsClient::~PrintCupsClient()
122 {}
123
StartCupsdService()124 int32_t PrintCupsClient::StartCupsdService()
125 {
126 PRINT_HILOGD("StartCupsdService enter");
127 if (!IsCupsServerAlive()) {
128 PRINT_HILOGI("The cupsd process is not started, start it now.");
129 int result = SetParameter(CUPSD_CONTROL_PARAM.c_str(), "true");
130 if (result) {
131 PRINT_HILOGD("SetParameter failed: %{public}d.", result);
132 return E_PRINT_SERVER_FAILURE;
133 }
134 const int bufferSize = 96;
135 char value[bufferSize] = {0};
136 GetParameter(CUPSD_CONTROL_PARAM.c_str(), "", value, bufferSize-1);
137 PRINT_HILOGD("print.cupsd.ready value: %{public}s.", value);
138 return E_PRINT_NONE;
139 }
140 std::string pidFile = CUPS_RUN_DIR + "/cupsd.pid";
141 struct stat sb;
142 if (stat(pidFile.c_str(), &sb) != 0) {
143 PRINT_HILOGI("stat pidFile failed.");
144 return E_PRINT_SERVER_FAILURE;
145 }
146 char realPidFile[PATH_MAX] = {};
147 if (realpath(pidFile.c_str(), realPidFile) == nullptr) {
148 PRINT_HILOGE("The realPidFile is null.");
149 return E_PRINT_SERVER_FAILURE;
150 }
151 int fd;
152 if ((fd = open(realPidFile, O_RDONLY)) < 0) {
153 PRINT_HILOGE("Open pidFile error!");
154 return E_PRINT_SERVER_FAILURE;
155 }
156 lseek(fd, 0, SEEK_SET);
157 char buf[BUFFER_LEN] = {0};
158 if ((read(fd, buf, sb.st_size)) < 0) {
159 PRINT_HILOGE("Read pidFile error!");
160 close(fd);
161 return E_PRINT_SERVER_FAILURE;
162 }
163 close(fd);
164 PRINT_HILOGD("The Process of CUPSD has existed, pid: %{public}s.", buf);
165 return E_PRINT_NONE;
166 }
167
ChangeFilterPermission(const std::string & path,mode_t mode)168 void PrintCupsClient::ChangeFilterPermission(const std::string &path, mode_t mode)
169 {
170 DIR *dir = opendir(path.c_str());
171 if (dir == nullptr) {
172 return;
173 }
174 struct dirent *entry;
175 while ((entry = readdir(dir)) != nullptr) {
176 std::string fileName = entry->d_name;
177 if (fileName == "." || fileName == "..") {
178 continue;
179 }
180 std::string filePath = path + "/" + fileName;
181 struct stat fileStat;
182 if (stat(filePath.c_str(), &fileStat) == -1) {
183 continue;
184 }
185 if (S_ISDIR(fileStat.st_mode)) {
186 ChangeFilterPermission(filePath.c_str(), mode);
187 } else if (S_ISREG(fileStat.st_mode)) {
188 if (chmod(filePath.c_str(), mode) == -1) {
189 PRINT_HILOGE("Failed to change mode: %{private}s", filePath.c_str());
190 }
191 }
192 }
193 closedir(dir);
194 }
195
SymlinkFile(std::string srcFilePath,std::string destFilePath)196 void PrintCupsClient::SymlinkFile(std::string srcFilePath, std::string destFilePath)
197 {
198 int ret = symlink(srcFilePath.c_str(), destFilePath.c_str());
199 if (!ret) {
200 PRINT_HILOGE("symlink success, ret = %{public}d, errno = %{public}d", ret, errno);
201 } else {
202 PRINT_HILOGE("symlink failed, ret = %{public}d, errno = %{public}d", ret, errno);
203 }
204 }
205
SymlinkDirectory(const char * srcDir,const char * destDir)206 void PrintCupsClient::SymlinkDirectory(const char *srcDir, const char *destDir)
207 {
208 DIR *dir = opendir(srcDir);
209 if (dir == nullptr) {
210 PRINT_HILOGE("Failed to open Dir: %{private}s", srcDir);
211 return;
212 }
213 if (access(destDir, F_OK)) {
214 mkdir(destDir, DIR_MODE);
215 }
216 struct dirent *file;
217 struct stat filestat = {};
218 struct stat destFilestat = {};
219 while ((file = readdir(dir)) != nullptr) {
220 if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, "..")) {
221 continue;
222 }
223 std::string srcFilePath = std::string(srcDir) + "/" + std::string(file->d_name);
224 std::string destFilePath = std::string(destDir) + "/" + std::string(file->d_name);
225
226 stat(srcFilePath.c_str(), &filestat);
227 if (S_ISDIR(filestat.st_mode)) {
228 SymlinkDirectory(srcFilePath.c_str(), destFilePath.c_str());
229 } else if (lstat(destFilePath.c_str(), &destFilestat) == 0) {
230 PRINT_HILOGD("symlink lstat %{public}s err: %{public}s", destFilePath.c_str(), strerror(errno));
231
232 if (S_ISLNK(destFilestat.st_mode)) {
233 PRINT_HILOGW("symlink already exists, continue.");
234 continue;
235 }
236 if (std::remove(destFilePath.c_str()) != 0) {
237 PRINT_HILOGE("error deleting file %{public}s err: %{public}s",
238 destFilePath.c_str(), strerror(errno));
239 continue;
240 } else {
241 PRINT_HILOGW("file successfully deleted");
242 }
243 SymlinkFile(srcFilePath, destFilePath);
244 } else {
245 PRINT_HILOGE("symlink lstat %{public}s err: %{public}s", destFilePath.c_str(), strerror(errno));
246 SymlinkFile(srcFilePath, destFilePath);
247 }
248 }
249 closedir(dir);
250 }
251
CopyDirectory(const char * srcDir,const char * destDir)252 void PrintCupsClient::CopyDirectory(const char *srcDir, const char *destDir)
253 {
254 DIR *dir = opendir(srcDir);
255 if (dir == nullptr) {
256 PRINT_HILOGE("Failed to open Dir: %{private}s", srcDir);
257 return;
258 }
259 if (access(destDir, F_OK) != 0) {
260 mkdir(destDir, DIR_MODE);
261 }
262 struct dirent *file;
263 struct stat filestat;
264 while ((file = readdir(dir)) != nullptr) {
265 if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) {
266 continue;
267 }
268 std::string srcFilePath = std::string(srcDir) + "/" + std::string(file->d_name);
269 std::string destFilePath = std::string(destDir) + "/" + std::string(file->d_name);
270
271 stat(srcFilePath.c_str(), &filestat);
272 if (S_ISDIR(filestat.st_mode)) {
273 CopyDirectory(srcFilePath.c_str(), destFilePath.c_str());
274 chmod(destFilePath.c_str(), filestat.st_mode);
275 } else {
276 char realSrc[PATH_MAX] = {};
277 char destSrc[PATH_MAX] = {};
278 if (realpath(srcFilePath.c_str(), realSrc) == nullptr ||
279 realpath(destDir, destSrc) == nullptr) {
280 PRINT_HILOGE("The realSrc is null.");
281 continue;
282 }
283 FILE *srcFile = fopen(realSrc, "rb");
284 if (srcFile == nullptr) {
285 continue;
286 }
287 FILE *destFile = fopen(destFilePath.c_str(), "wb");
288 if (destFile == nullptr) {
289 fclose(srcFile);
290 continue;
291 }
292 char buffer[4096];
293 size_t bytesRead;
294 while ((bytesRead = fread(buffer, 1, sizeof(buffer), srcFile)) > 0) {
295 fwrite(buffer, 1, bytesRead, destFile);
296 }
297 fclose(srcFile);
298 fclose(destFile);
299 chmod(destFilePath.c_str(), filestat.st_mode);
300 }
301 }
302 closedir(dir);
303 }
304
InitCupsResources()305 int32_t PrintCupsClient::InitCupsResources()
306 {
307 string array[RESOURCE_COUNT][DIR_COUNT] = {
308 {"/system/bin/cups/", CUPS_ROOT_DIR + "/serverbin", CUPS_ROOT_DIR + "/serverbin/daemon"},
309 {"/system/etc/cups/share/", CUPS_ROOT_DIR + "/datadir", CUPS_ROOT_DIR + "/datadir/mime"}
310 };
311 for (uint32_t i = 0; i < RESOURCE_COUNT; i++) {
312 if (!i) {
313 SymlinkDirectory(array[i][INDEX_ZERO].c_str(), array[i][INDEX_ONE].c_str());
314 } else {
315 if (access(array[i][INDEX_TWO].c_str(), F_OK) != -1) {
316 PRINT_HILOGD("The resource has been copied.");
317 continue;
318 }
319 CopyDirectory(array[i][INDEX_ZERO].c_str(), array[i][INDEX_ONE].c_str());
320 }
321 }
322 return StartCupsdService();
323 }
324
StopCupsdService()325 void PrintCupsClient::StopCupsdService()
326 {
327 PRINT_HILOGD("StopCupsdService enter");
328 if (!IsCupsServerAlive()) {
329 PRINT_HILOGI("The cupsd process is not started, no need stop.");
330 return;
331 }
332 PRINT_HILOGI("The cupsd process is started, stop it now.");
333 int result = SetParameter(CUPSD_CONTROL_PARAM.c_str(), "false");
334 if (result) {
335 PRINT_HILOGD("SetParameter failed: %{public}d.", result);
336 return;
337 }
338 const int bufferSize = 96;
339 char value[bufferSize] = {0};
340 GetParameter(CUPSD_CONTROL_PARAM.c_str(), "", value, bufferSize-1);
341 PRINT_HILOGD("print.cupsd.ready value: %{public}s.", value);
342 }
343
QueryPPDInformation(const char * makeModel,std::vector<std::string> & ppds)344 void PrintCupsClient::QueryPPDInformation(const char *makeModel, std::vector<std::string> &ppds)
345 {
346 ipp_t *request;
347 ipp_t *response;
348 const char *ppd_make_model;
349 const char *ppd_name;
350
351 request = ippNewRequest(CUPS_GET_PPDS);
352 if (makeModel)
353 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model", NULL, makeModel);
354
355 PRINT_HILOGD("CUPS_GET_PPDS start.");
356 if ((response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) != NULL) {
357 if (response->request.status.status_code > IPP_OK_CONFLICT) {
358 PRINT_HILOGE("GetAvaiablePPDS failed: %{public}s", cupsLastErrorString());
359 ippDelete(response);
360 return;
361 }
362 ParsePPDInfo(response, ppd_make_model, ppd_name, ppds);
363 ippDelete(response);
364 } else {
365 PRINT_HILOGE("GetAvaiablePPDS failed: %{public}s", cupsLastErrorString());
366 }
367 }
368
ParsePPDInfo(ipp_t * response,const char * ppd_make_model,const char * ppd_name,std::vector<std::string> & ppds)369 void PrintCupsClient::ParsePPDInfo(ipp_t *response, const char *ppd_make_model, const char *ppd_name,
370 std::vector<std::string> &ppds)
371 {
372 if (response == nullptr) {
373 return;
374 }
375 for (ipp_attribute_t *attr = response->attrs; attr != NULL; attr = attr->next) {
376 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
377 attr = attr->next;
378 if (attr == NULL) {
379 break;
380 }
381 ppd_make_model = NULL;
382 ppd_name = NULL;
383
384 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
385 if (!strcmp(attr->name, "ppd-make-and-model") && attr->value_tag == IPP_TAG_TEXT)
386 ppd_make_model = attr->values[0].string.text;
387 else if (!strcmp(attr->name, "ppd-name") && attr->value_tag == IPP_TAG_NAME)
388 ppd_name = attr->values[0].string.text;
389 attr = attr->next;
390 }
391 if (ppd_make_model == NULL || ppd_name == NULL) {
392 if (attr == NULL)
393 break;
394 else
395 continue;
396 }
397 ppds.push_back(ppd_name);
398 PRINT_HILOGI("ppd: name = %{private}s, make-and-model = %{private}s", ppd_name, ppd_make_model);
399 if (attr == NULL)
400 break;
401 }
402 }
403
AddPrinterToCups(const std::string & printerUri,const std::string & printerName,const std::string & printerMake)404 int32_t PrintCupsClient::AddPrinterToCups(const std::string &printerUri, const std::string &printerName,
405 const std::string &printerMake)
406 {
407 PRINT_HILOGD("PrintCupsClient AddPrinterToCups start, printerMake: %{public}s", printerMake.c_str());
408 ipp_t *request;
409 http_t *http = NULL;
410 char uri[HTTP_MAX_URI];
411 std::vector<string> ppds;
412 std::string ppd = DEFAULT_PPD_NAME;
413 std::string standardName = PrintUtil::StandardizePrinterName(printerName);
414
415 ippSetPort(CUPS_SEVER_PORT);
416 QueryPPDInformation(printerMake.c_str(), ppds);
417 if (!ppds.empty()) {
418 ppd = ppds[0];
419 std::string serverBin = CUPS_ROOT_DIR + "/serverbin";
420 mode_t permissions = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH;
421 ChangeFilterPermission(serverBin, permissions);
422 }
423 PRINT_HILOGI("ppd driver: %{public}s", ppd.c_str());
424 if (IsPrinterExist(printerUri.c_str(), standardName.c_str(), ppd.c_str())) {
425 PRINT_HILOGI("add success, printer has added");
426 return E_PRINT_NONE;
427 }
428 request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
429 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s",
430 standardName.c_str());
431 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
432 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
433 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, standardName.c_str());
434 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, printerUri.c_str());
435 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
436 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name", NULL, ppd.c_str());
437 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
438 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-shared", 1);
439 PRINT_HILOGD("IPP_OP_CUPS_ADD_MODIFY_PRINTER cupsDoRequest");
440 ippDelete(cupsDoRequest(http, request, "/admin/"));
441 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
442 PRINT_HILOGE("add error: %s", cupsLastErrorString());
443 return E_PRINT_SERVER_FAILURE;
444 }
445 httpClose(http);
446 PRINT_HILOGI("add success");
447 return E_PRINT_NONE;
448 }
449
DeletePrinterFromCups(const std::string & printerUri,const std::string & printerName,const std::string & printerMake)450 int32_t PrintCupsClient::DeletePrinterFromCups(const std::string &printerUri, const std::string &printerName,
451 const std::string &printerMake)
452 {
453 PRINT_HILOGD("PrintCupsClient DeletePrinterFromCups start, printerMake: %{public}s", printerMake.c_str());
454 ipp_t *request;
455 http_t *http = NULL;
456 char uri[HTTP_MAX_URI];
457 std::vector<string> ppds;
458 std::string ppd = DEFAULT_PPD_NAME;
459 std::string standardName = PrintUtil::StandardizePrinterName(printerName);
460
461 ippSetPort(CUPS_SEVER_PORT);
462 QueryPPDInformation(printerMake.c_str(), ppds);
463 if (!ppds.empty()) {
464 ppd = ppds[0];
465 std::string serverBin = CUPS_ROOT_DIR + "/serverbin";
466 mode_t permissions = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH;
467 ChangeFilterPermission(serverBin, permissions);
468 }
469 PRINT_HILOGI("ppd driver: %{public}s", ppd.c_str());
470 if (!IsPrinterExist(printerUri.c_str(), standardName.c_str(), ppd.c_str())) {
471 PRINT_HILOGI("printer has not added");
472 return E_PRINT_NONE;
473 }
474 request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
475 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s",
476 standardName.c_str());
477 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
478 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
479 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, standardName.c_str());
480 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, printerUri.c_str());
481 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name", NULL, ppd.c_str());
482 PRINT_HILOGD("IPP_OP_CUPS_DELETE_PRINTER cupsDoRequest");
483 ippDelete(cupsDoRequest(http, request, "/admin/"));
484 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
485 PRINT_HILOGE("delete error: %s", cupsLastErrorString());
486 return E_PRINT_SERVER_FAILURE;
487 }
488 httpClose(http);
489 PRINT_HILOGI("delete success");
490 return E_PRINT_NONE;
491 }
492
DeleteCupsPrinter(const char * printerName)493 int32_t PrintCupsClient::DeleteCupsPrinter(const char *printerName)
494 {
495 ipp_t *request;
496 char uri[HTTP_MAX_URI];
497 http_t *http = NULL;
498
499 PRINT_HILOGD("PrintCupsClient DeleteCupsPrinter start: %{private}s", printerName);
500 request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
501 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printerName);
502 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
503 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
504 ippDelete(cupsDoRequest(http, request, "/admin/"));
505 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
506 PRINT_HILOGE("DeleteCupsPrinter error: %{public}s", cupsLastErrorString());
507 return E_PRINT_SERVER_FAILURE;
508 }
509 return E_PRINT_NONE;
510 }
511
QueryPrinterCapabilityByUri(const std::string & printerUri,const std::string & printerId,PrinterCapability & printerCaps)512 int32_t PrintCupsClient::QueryPrinterCapabilityByUri(const std::string &printerUri, const std::string &printerId,
513 PrinterCapability &printerCaps)
514 {
515 PRINT_HILOGD("PrintCupsClient QueryPrinterCapabilityByUri start.");
516 ipp_t *request; /* IPP Request */
517 ipp_t *response; /* IPP Request */
518 http_t *http = NULL;
519 char scheme[HTTP_MAX_URI]; /* Method portion of URI */
520 char username[HTTP_MAX_URI]; /* Username portion of URI */
521 char host[HTTP_MAX_URI]; /* Host portion of URI */
522 char resource[HTTP_MAX_URI]; /* Resource portion of URI */
523 int port; /* Port portion of URI */
524
525 static const char * const pattrs[] = {
526 "all"
527 };
528 PRINT_HILOGD("QueryPrinterCapabilityByUri enter");
529 httpSeparateURI(HTTP_URI_CODING_ALL, printerUri.c_str(), scheme, sizeof(scheme), username, sizeof(username), host,
530 sizeof(host), &port, resource, sizeof(resource));
531
532 std::string nic;
533 if (IsIpConflict(printerId, nic)) {
534 http = httpConnect3(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, TIME_OUT, NULL, nic.c_str());
535 } else {
536 http = httpConnect2(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, TIME_OUT, NULL);
537 }
538 if (http == nullptr) {
539 PRINT_HILOGD("connect printer failed");
540 return E_PRINT_SERVER_FAILURE;
541 }
542 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
543 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printerUri.c_str());
544 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
545 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", 1, NULL, pattrs);
546 response = cupsDoRequest(http, request, "/");
547
548 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
549 PRINT_HILOGE("set default printers error: %{public}s", cupsLastErrorString());
550 ippDelete(response);
551 return E_PRINT_SERVER_FAILURE;
552 }
553 PRINT_HILOGD("get caps success: %{public}s", cupsLastErrorString());
554 ParsePrinterAttributes(response, printerCaps);
555 httpClose(http);
556 return E_PRINT_NONE;
557 }
558
AddCupsPrintJob(const PrintJob & jobInfo)559 void PrintCupsClient::AddCupsPrintJob(const PrintJob &jobInfo)
560 {
561 JobParameters *jobParams = BuildJobParameters(jobInfo);
562 if (jobParams == nullptr) {
563 return;
564 }
565 DumpJobParameters(jobParams);
566 jobQueue_.push_back(jobParams);
567 StartNextJob();
568 }
569
StartNextJob()570 void PrintCupsClient::StartNextJob()
571 {
572 if (jobQueue_.empty()) {
573 PRINT_HILOGE("no active job in jobQueue_");
574 return;
575 }
576 if (currentJob_ != nullptr) {
577 JobParameters *lastJob = jobQueue_.back();
578 if (lastJob != nullptr) {
579 PrintServiceAbility::GetInstance()->UpdatePrintJobState(lastJob->serviceJobId, PRINT_JOB_QUEUED,
580 PRINT_JOB_BLOCKED_UNKNOWN);
581 }
582 PRINT_HILOGE("a active job is running, job len: %{public}zd", jobQueue_.size());
583 return;
584 }
585 PRINT_HILOGI("start next job from queue");
586
587 currentJob_ = jobQueue_.at(0);
588 jobQueue_.erase(jobQueue_.begin());
589 if (!currentJob_) {
590 PRINT_HILOGE("currentJob_ is nullptr");
591 return;
592 }
593 auto self = shared_from_this();
594 CallbackFunc callback = [self]() { self->JobCompleteCallback(); };
595 std::thread StartPrintThread([self, callback] {self->StartCupsJob(self->currentJob_, callback);});
596 StartPrintThread.detach();
597 }
598
JobCompleteCallback()599 void PrintCupsClient::JobCompleteCallback()
600 {
601 PRINT_HILOGI("Previous job complete, start next job");
602 if (!currentJob_) {
603 free(currentJob_);
604 }
605 currentJob_ = nullptr;
606 StartNextJob();
607 }
608
FillBorderlessOptions(JobParameters * jobParams,int num_options,cups_option_t ** options)609 int PrintCupsClient::FillBorderlessOptions(JobParameters *jobParams, int num_options, cups_option_t **options)
610 {
611 if (jobParams->borderless == 1 && jobParams->mediaType == CUPS_MEDIA_TYPE_PHOTO_GLOSSY) {
612 PRINT_HILOGD("borderless job options");
613 std::vector<MediaSize> mediaSizes;
614 mediaSizes.push_back({ CUPS_MEDIA_4X6, 4000, 6000 });
615 mediaSizes.push_back({ CUPS_MEDIA_5X7, 5000, 7000 });
616 mediaSizes.push_back({ CUPS_MEDIA_A4, 8268, 11692 });
617 int sizeIndex = -1;
618 float meidaWidth = 0;
619 float mediaHeight = 0;
620 for (int i = 0; i < static_cast<int>(mediaSizes.size()); i++) {
621 if (mediaSizes[i].name == jobParams->mediaSize) {
622 sizeIndex = i;
623 break;
624 }
625 }
626 if (sizeIndex >= 0) {
627 meidaWidth = floorf(ConvertInchTo100MM(mediaSizes[sizeIndex].WidthInInches));
628 mediaHeight = floorf(ConvertInchTo100MM(mediaSizes[sizeIndex].HeightInInches));
629 } else {
630 meidaWidth = floorf(ConvertInchTo100MM(mediaSizes[0].WidthInInches));
631 mediaHeight = floorf(ConvertInchTo100MM(mediaSizes[0].HeightInInches));
632 }
633 PRINT_HILOGD("meidaWidth: %f", meidaWidth);
634 PRINT_HILOGD("mediaHeight: %f", mediaHeight);
635 std::stringstream value;
636 value << "{media-size={x-dimension=" << meidaWidth << " y-dimension=" << mediaHeight;
637 value << "} media-bottom-margin=" << 0 << " media-left-margin=" << 0 << " media-right-margin=" << 0;
638 value << " media-top-margin=" << 0 << " media-type=\"" << jobParams->mediaType << "\"}";
639 PRINT_HILOGD("value: %s", value.str().c_str());
640 num_options = cupsAddOption("media-col", value.str().c_str(), num_options, options);
641 } else {
642 PRINT_HILOGD("not borderless job options");
643 if (!jobParams->mediaSize.empty()) {
644 num_options = cupsAddOption(CUPS_MEDIA, jobParams->mediaSize.c_str(), num_options, options);
645 } else {
646 num_options = cupsAddOption(CUPS_MEDIA, CUPS_MEDIA_A4, num_options, options);
647 }
648 if (!jobParams->mediaType.empty()) {
649 num_options = cupsAddOption(CUPS_MEDIA_TYPE, jobParams->mediaType.c_str(), num_options, options);
650 } else {
651 num_options = cupsAddOption(CUPS_MEDIA_TYPE, CUPS_MEDIA_TYPE_PLAIN, num_options, options);
652 }
653 }
654 return num_options;
655 }
656
FillJobOptions(JobParameters * jobParams,int num_options,cups_option_t ** options)657 int PrintCupsClient::FillJobOptions(JobParameters *jobParams, int num_options, cups_option_t **options)
658 {
659 if (jobParams->numCopies >= 1) {
660 num_options = cupsAddIntegerOption(CUPS_COPIES, jobParams->numCopies, num_options, options);
661 } else {
662 num_options = cupsAddIntegerOption(CUPS_COPIES, 1, num_options, options);
663 }
664
665 if (!jobParams->duplex.empty()) {
666 num_options = cupsAddOption(CUPS_SIDES, jobParams->duplex.c_str(), num_options, options);
667 } else {
668 num_options = cupsAddOption(CUPS_SIDES, CUPS_SIDES_ONE_SIDED, num_options, options);
669 }
670 if (!jobParams->printQuality.empty()) {
671 num_options = cupsAddOption(CUPS_PRINT_QUALITY, jobParams->printQuality.c_str(), num_options, options);
672 } else {
673 num_options = cupsAddOption(CUPS_PRINT_QUALITY, CUPS_PRINT_QUALITY_NORMAL, num_options, options);
674 }
675 if (!jobParams->color.empty()) {
676 num_options = cupsAddOption(CUPS_PRINT_COLOR_MODE, jobParams->color.c_str(), num_options, options);
677 } else {
678 num_options = cupsAddOption(CUPS_PRINT_COLOR_MODE, CUPS_PRINT_COLOR_MODE_AUTO, num_options, options);
679 }
680 std::string nic;
681 if (IsIpConflict(jobParams->printerId, nic)) {
682 num_options = cupsAddOption("nic", nic.c_str(), num_options, options);
683 }
684 num_options = FillBorderlessOptions(jobParams, num_options, options);
685 return num_options;
686 }
687
QueryAddedPrinterList(std::vector<std::string> & printerNameList)688 int32_t PrintCupsClient::QueryAddedPrinterList(std::vector<std::string> &printerNameList)
689 {
690 if (!IsCupsServerAlive()) {
691 PRINT_HILOGI("The cupsd process is not started, start it now.");
692 int32_t ret = StartCupsdService();
693 if (ret != 0) {
694 return E_PRINT_SERVER_FAILURE;
695 }
696 }
697 printerNameList.clear();
698 cups_dest_t *dests = NULL;
699 int num = cupsGetDests(&dests);
700 PRINT_HILOGI("QueryAddedPrinterList, num: %{public}d.", num);
701 for (int i = 0; i < num; i++) {
702 PRINT_HILOGD("QueryAddedPrinterList, printerIsDefault: %{public}d.", dests[i].is_default);
703 printerNameList.emplace_back(dests[i].name);
704 }
705 cupsFreeDests(num, dests);
706 return E_PRINT_NONE;
707 }
708
SetDefaultPrinter(const std::string & printerName)709 int32_t PrintCupsClient::SetDefaultPrinter(const std::string &printerName)
710 {
711 http_t *http;
712 ippSetPort(CUPS_SEVER_PORT);
713 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, LONG_TIME_OUT, NULL);
714 if (http == nullptr) {
715 PRINT_HILOGE("cups server is not alive");
716 return E_PRINT_SERVER_FAILURE;
717 }
718 ipp_t *request; /* IPP Request */
719 char uri[HTTP_MAX_URI]; /* URI for printer/class */
720 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
721 "localhost", 0, "/printers/%s", printerName.c_str());
722 request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
723 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
724 "printer-uri", NULL, uri);
725 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
726 NULL, cupsUser());
727 ippDelete(cupsDoRequest(http, request, "/admin/"));
728
729 const char* default_printer = cupsGetDefault();
730 PRINT_HILOGI("default_printer=%{public}s", default_printer);
731 if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
732 PRINT_HILOGI("[ERROR] occur a error when do cups-request{setDefault}. error is:> ");
733 return E_PRINT_SERVER_FAILURE;
734 }
735 return E_PRINT_NONE;
736 }
737
GetPPDFile(const std::string & printerName)738 ppd_file_t* PrintCupsClient::GetPPDFile(const std::string &printerName)
739 {
740 if (!IsCupsServerAlive()) {
741 PRINT_HILOGI("The cupsd process is not started, start it now.");
742 int32_t ret = StartCupsdService();
743 if (ret != 0) {
744 return nullptr;
745 }
746 }
747 ppd_file_t *ppd = 0;
748 std::string fileDir = "/data/service/el1/public/print_service/cups/ppd/";
749 std::string pName = printerName;
750 std::string filePath = fileDir + pName + ".ppd";
751 PRINT_HILOGI("GetPPDFile started filePath %{public}s", filePath.c_str());
752 char realPath[PATH_MAX] = {};
753 if (realpath(filePath.c_str(), realPath) == nullptr) {
754 PRINT_HILOGE("The realPidFile is null.");
755 return nullptr;
756 }
757 int fd;
758 if ((fd = open(realPath, O_RDWR)) < 0) {
759 PRINT_HILOGE("Open ppdFile error!");
760 return nullptr;
761 }
762 PRINT_HILOGI("GetPPDFile %{public}d", fd);
763 ppd = ppdOpenFd(fd);
764 close(fd);
765 PRINT_HILOGI("GetPPDFile groups:%{public}d,pagesize_num:%{public}d", ppd->num_groups, ppd->num_sizes);
766 return ppd;
767 }
768
QueryPrinterAttrList(const std::string & printerName,const std::vector<std::string> & keyList,std::vector<std::string> & valueList)769 int32_t PrintCupsClient::QueryPrinterAttrList(const std::string &printerName, const std::vector<std::string> &keyList,
770 std::vector<std::string> &valueList)
771 {
772 cups_dest_t *dest = nullptr;
773 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printerName.c_str(), NULL);
774 if (dest == nullptr) {
775 PRINT_HILOGW("the printer is not found");
776 return E_PRINT_SERVER_FAILURE;
777 }
778 for (auto &key : keyList) {
779 const char *ret = cupsGetOption(key.c_str(), dest->num_options, dest ->options);
780 if (ret != NULL) {
781 std::string valueStr = ret;
782 std::string value = key + "&" + valueStr;
783 valueList.emplace_back(value);
784 }
785 }
786 PRINT_HILOGI("QueryPrinterAttr end");
787 return E_PRINT_NONE;
788 }
789
QueryPrinterInfoByPrinterId(const std::string & printerId,PrinterInfo & info)790 int32_t PrintCupsClient::QueryPrinterInfoByPrinterId(const std::string& printerId, PrinterInfo &info)
791 {
792 PRINT_HILOGD("the printerInfo printerName %{public}s", info.GetPrinterName().c_str());
793 cups_dest_t *dest = nullptr;
794 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, info.GetPrinterName().c_str(), NULL);
795 if (dest == nullptr) {
796 PRINT_HILOGW("the printer is not found");
797 return E_PRINT_SERVER_FAILURE;
798 }
799 if (info.HasOption()) {
800 PRINT_HILOGI("the printerInfo option");
801 PrinterCapability printerCaps;
802 std::string infoOpt = info.GetOption();
803 PRINT_HILOGD("the printerInfo option %{public}s", infoOpt.c_str());
804 if (!json::accept(infoOpt)) {
805 PRINT_HILOGE("infoOpt can not parse to json object");
806 return E_PRINT_INVALID_PARAMETER;
807 }
808 nlohmann::json infoJson = nlohmann::json::parse(infoOpt);
809 if (!infoJson.contains("printerUri") || !infoJson["printerUri"].is_string()) {
810 PRINT_HILOGE("The infoJson does not have a necessary printerUri attribute.");
811 return E_PRINT_INVALID_PARAMETER;
812 }
813 std::string printerUri = infoJson["printerUri"].get<std::string>();
814 PRINT_HILOGD("QueryPrinterInfoByPrinterId in %{public}s", printerUri.c_str());
815 if (infoJson.contains("printerName") && infoJson["printerName"].is_string()) {
816 info.SetPrinterName(infoJson["printerName"].get<std::string>());
817 }
818 int32_t ret = QueryPrinterCapabilityByUri(printerUri, printerId, printerCaps);
819 PRINT_HILOGI("QueryPrinterInfoByPrinterId out");
820 if (ret != 0) {
821 PRINT_HILOGE("QueryPrinterInfoByPrinterId QueryPrinterCapabilityByUri fail");
822 return E_PRINT_SERVER_FAILURE;
823 }
824 nlohmann::json cupsOptionsJson = printerCaps.GetPrinterAttrGroupJson();
825 infoJson["cupsOptions"] = cupsOptionsJson;
826 info.SetOption(infoJson.dump());
827 info.Dump();
828 }
829 return E_PRINT_NONE;
830 }
831
CheckPrinterMakeModel(JobParameters * jobParams)832 bool PrintCupsClient::CheckPrinterMakeModel(JobParameters *jobParams)
833 {
834 cups_dest_t *dest = nullptr;
835 bool isMakeModelRight = false;
836 uint32_t retryCount = 0;
837 PRINT_HILOGD("CheckPrinterMakeModel start.");
838 if (jobParams == nullptr) {
839 PRINT_HILOGE("The jobParams is null");
840 return isMakeModelRight;
841 }
842 while (retryCount < MAX_RETRY_TIMES) {
843 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, jobParams->printerName.c_str(), NULL);
844 if (dest != NULL) {
845 const char *makeModel = cupsGetOption("printer-make-and-model", dest->num_options, dest->options);
846 PRINT_HILOGD("makeModel=%{private}s", makeModel);
847 if (strcmp(makeModel, "Local Raw Printer") != 0) {
848 isMakeModelRight = true;
849 cupsFreeDests(1, dest);
850 break;
851 }
852 cupsFreeDests(1, dest);
853 } else {
854 PRINT_HILOGE("The dest is null");
855 }
856 retryCount++;
857 sleep(INDEX_TWO);
858 }
859 return isMakeModelRight;
860 }
861
VerifyPrintJob(JobParameters * jobParams,int & num_options,uint32_t & jobId,cups_option_t * options,http_t * http)862 bool PrintCupsClient::VerifyPrintJob(JobParameters *jobParams, int &num_options, uint32_t &jobId,
863 cups_option_t *options, http_t *http)
864 {
865 if (jobParams == nullptr) {
866 PRINT_HILOGE("The jobParams is null");
867 return false;
868 }
869 uint32_t retryCount = 0;
870 bool isPrinterOnline = false;
871
872 JobMonitorParam *monitorParam = new (std::nothrow) JobMonitorParam { jobParams->serviceAbility,
873 jobParams->serviceJobId, jobId, jobParams->printerUri, jobParams->printerName, jobParams->printerId };
874 if (monitorParam == nullptr) {
875 PRINT_HILOGE("monitorParam is null");
876 return false;
877 }
878 while (retryCount < MAX_RETRY_TIMES) {
879 if (CheckPrinterOnline(monitorParam)) {
880 isPrinterOnline = true;
881 break;
882 }
883 retryCount++;
884 sleep(INDEX_ONE);
885 }
886 delete monitorParam;
887 monitorParam = nullptr;
888 if (!isPrinterOnline) {
889 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, PRINT_JOB_BLOCKED,
890 PRINT_JOB_BLOCKED_OFFLINE);
891 return false;
892 }
893 if (!CheckPrinterMakeModel(jobParams)) {
894 PRINT_HILOGE("VerifyPrintJob printer make model is error");
895 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, PRINT_JOB_BLOCKED,
896 PRINT_JOB_BLOCKED_DRIVER_EXCEPTION);
897 return false;
898 }
899 num_options = FillJobOptions(jobParams, num_options, &options);
900 if ((jobId = static_cast<uint32_t>(cupsCreateJob(http, jobParams->printerName.c_str(), jobParams->jobName.c_str(),
901 num_options, options))) == 0) {
902 PRINT_HILOGE("Unable to cupsCreateJob: %s", cupsLastErrorString());
903 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, PRINT_JOB_BLOCKED,
904 PRINT_JOB_BLOCKED_SERVER_CONNECTION_ERROR);
905 return false;
906 }
907 return true;
908 }
StartCupsJob(JobParameters * jobParams,CallbackFunc callback)909 void PrintCupsClient::StartCupsJob(JobParameters *jobParams, CallbackFunc callback)
910 {
911 http_t *http = nullptr;
912 int num_options = 0;
913 cups_option_t *options = nullptr;
914 cups_file_t *fp = nullptr;
915 uint32_t jobId;
916 http_status_t status;
917 char buffer[8192];
918 ssize_t bytes = -1;
919
920 if (!VerifyPrintJob(jobParams, num_options, jobId, options, http)) {
921 callback();
922 return;
923 }
924 uint32_t num_files = jobParams->fdList.size();
925 PRINT_HILOGD("StartCupsJob fill job options, num_files: %{public}d", num_files);
926 for (uint32_t i = 0; i < num_files; i++) {
927 if ((fp = cupsFileOpenFd(jobParams->fdList[i], "rb")) == NULL) {
928 PRINT_HILOGE("Unable to open print file, cancel the job");
929 cupsCancelJob2(http, jobParams->printerName.c_str(), jobId, 0);
930 UpdatePrintJobStateInJobParams(jobParams, PRINT_JOB_BLOCKED, PRINT_JOB_COMPLETED_FILE_CORRUPT);
931 callback();
932 return;
933 }
934 status = cupsStartDocument(http, jobParams->printerName.c_str(), jobId, jobParams->jobName.c_str(),
935 jobParams->documentFormat.c_str(), i == (num_files - 1));
936 if (status == HTTP_STATUS_CONTINUE)
937 bytes = cupsFileRead(fp, buffer, sizeof(buffer));
938 while (status == HTTP_STATUS_CONTINUE && bytes > 0) {
939 status = cupsWriteRequestData(http, buffer, (size_t)bytes);
940 bytes = cupsFileRead(fp, buffer, sizeof(buffer));
941 }
942 cupsFileClose(fp);
943 if (status != HTTP_STATUS_CONTINUE || cupsFinishDocument(http, jobParams->printerName.c_str())
944 != IPP_STATUS_OK) {
945 PRINT_HILOGE("Unable to queue, error is %s, cancel the job and return...", cupsLastErrorString());
946 cupsCancelJob2(http, jobParams->printerUri.c_str(), jobId, 0);
947 UpdatePrintJobStateInJobParams(jobParams, PRINT_JOB_BLOCKED, PRINT_JOB_BLOCKED_UNKNOWN);
948 callback();
949 return;
950 }
951 }
952 jobParams->cupsJobId = jobId;
953 PRINT_HILOGD("start job success, jobId: %d", jobId);
954 JobMonitorParam *param = new (std::nothrow) JobMonitorParam { jobParams->serviceAbility,
955 jobParams->serviceJobId, jobId, jobParams->printerUri, jobParams->printerName, jobParams->printerId };
956 if (param == nullptr)
957 return;
958 g_isFirstQueryState = true;
959 MonitorJobState(param, callback);
960 }
961
UpdatePrintJobStateInJobParams(JobParameters * jobParams,uint32_t state,uint32_t subState)962 void PrintCupsClient::UpdatePrintJobStateInJobParams(JobParameters *jobParams, uint32_t state, uint32_t subState)
963 {
964 if (jobParams != nullptr && jobParams->serviceAbility != nullptr) {
965 jobParams->serviceAbility->UpdatePrintJobState(jobParams->serviceJobId, state, subState);
966 }
967 }
968
MonitorJobState(JobMonitorParam * param,CallbackFunc callback)969 void PrintCupsClient::MonitorJobState(JobMonitorParam *param, CallbackFunc callback)
970 {
971 http_t *http = NULL;
972 uint32_t fail_connect_times = 0;
973 PRINT_HILOGD("MonitorJobState enter, cupsJobId: %{public}d", param->cupsJobId);
974 ippSetPort(CUPS_SEVER_PORT);
975 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, LONG_TIME_OUT, NULL);
976 JobStatus *jobStatus = new (std::nothrow) JobStatus { {'\0'}, (ipp_jstate_t)0, {'\0'}};
977 JobStatus *prevousJobStatus = new (std::nothrow) JobStatus { {'\0'}, (ipp_jstate_t)0, {'\0'}};
978 while (jobStatus->job_state < IPP_JSTATE_CANCELED) {
979 if (httpGetFd(http) < 0) {
980 PRINT_HILOGE("http is NULL");
981 httpReconnect2(http, LONG_LONG_TIME_OUT, NULL);
982 }
983 if (httpGetFd(http) > 0 && CheckPrinterOnline(param)) {
984 fail_connect_times = 0;
985 QueryJobState(http, param, jobStatus);
986 if (g_isFirstQueryState) {
987 QueryJobStateAgain(http, param, jobStatus);
988 }
989 } else if (fail_connect_times < OFFLINE_RETRY_TIMES) {
990 PRINT_HILOGE("unable connect to printer, retry: %{public}d", fail_connect_times);
991 fail_connect_times++;
992 sleep(INTERVAL_FOR_QUERY);
993 continue;
994 } else {
995 PRINT_HILOGE("_start(): The maximum number of connection failures has been exceeded");
996 JobStatusCallback(param, jobStatus, true);
997 break;
998 }
999 if (jobStatus->job_state < IPP_JSTATE_CANCELED)
1000 sleep(INTERVAL_FOR_QUERY);
1001 if (jobStatus->job_state == 0) {
1002 PRINT_HILOGD("job_state is 0, continue");
1003 continue;
1004 }
1005 if (prevousJobStatus != nullptr && prevousJobStatus->job_state == jobStatus->job_state &&
1006 strcmp(prevousJobStatus->printer_state_reasons, jobStatus->printer_state_reasons) == 0) {
1007 PRINT_HILOGD("the prevous jobState is the same as current, ignore");
1008 continue;
1009 }
1010 UpdateJobStatus(prevousJobStatus, jobStatus);
1011 JobStatusCallback(param, jobStatus, false);
1012 }
1013 httpClose(http);
1014 delete param;
1015 delete jobStatus;
1016 delete prevousJobStatus;
1017 PRINT_HILOGI("FINISHED MONITORING JOB %{public}d\n", param->cupsJobId);
1018 callback();
1019 }
1020
QueryJobStateAgain(http_t * http,JobMonitorParam * param,JobStatus * jobStatus)1021 void PrintCupsClient::QueryJobStateAgain(http_t *http, JobMonitorParam *param, JobStatus *jobStatus)
1022 {
1023 sleep(INTERVAL_FOR_FIRST_QUERY);
1024 QueryJobState(http, param, jobStatus);
1025 g_isFirstQueryState = false;
1026 }
1027
UpdateJobStatus(JobStatus * prevousJobStatus,JobStatus * jobStatus)1028 void PrintCupsClient::UpdateJobStatus(JobStatus *prevousJobStatus, JobStatus *jobStatus)
1029 {
1030 if (prevousJobStatus != nullptr && jobStatus != nullptr) {
1031 prevousJobStatus->job_state = jobStatus->job_state;
1032 strlcpy(prevousJobStatus->printer_state_reasons,
1033 jobStatus->printer_state_reasons,
1034 sizeof(jobStatus->printer_state_reasons));
1035 }
1036 }
1037
JobStatusCallback(JobMonitorParam * param,JobStatus * jobStatus,bool isOffline)1038 void PrintCupsClient::JobStatusCallback(JobMonitorParam *param, JobStatus *jobStatus, bool isOffline)
1039 {
1040 PRINT_HILOGD("JobStatusCallback enter, job_state: %{public}d", jobStatus->job_state);
1041 PRINT_HILOGD("JobStatusCallback enter, printer_state_reasons: %{public}s", jobStatus->printer_state_reasons);
1042 if (isOffline) {
1043 cupsCancelJob2(CUPS_HTTP_DEFAULT, param->printerName.c_str(), param->cupsJobId, 0);
1044 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_BLOCKED,
1045 PRINT_JOB_BLOCKED_OFFLINE);
1046 return;
1047 }
1048 if (jobStatus->job_state == IPP_JOB_COMPLETED) {
1049 PRINT_HILOGD("IPP_JOB_COMPLETED");
1050 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_COMPLETED,
1051 PRINT_JOB_COMPLETED_SUCCESS);
1052 } else if (jobStatus->job_state == IPP_JOB_PROCESSING) {
1053 PRINT_HILOGD("IPP_JOB_PROCESSING");
1054 std::string printerState(jobStatus->printer_state_reasons);
1055 if (find(IGNORE_STATE_LIST.begin(), IGNORE_STATE_LIST.end(), printerState) != IGNORE_STATE_LIST.end()) {
1056 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_RUNNING,
1057 PRINT_JOB_BLOCKED_BUSY);
1058 } else {
1059 ReportBlockedReason(param, jobStatus);
1060 }
1061 } else if (jobStatus->job_state == IPP_JOB_CANCELED || jobStatus->job_state == IPP_JOB_ABORTED) {
1062 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_COMPLETED,
1063 PRINT_JOB_COMPLETED_CANCELLED);
1064 } else if (jobStatus->job_state == IPP_JOB_PENDING || jobStatus->job_state == IPP_JOB_HELD) {
1065 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_QUEUED,
1066 PRINT_JOB_BLOCKED_UNKNOWN);
1067 } else {
1068 PRINT_HILOGE("wrong job state: %{public}d", jobStatus->job_state);
1069 }
1070 }
1071
ReportBlockedReason(JobMonitorParam * param,JobStatus * jobStatus)1072 void PrintCupsClient::ReportBlockedReason(JobMonitorParam *param, JobStatus *jobStatus)
1073 {
1074 if (param == nullptr || param->serviceAbility == nullptr || jobStatus == nullptr) {
1075 PRINT_HILOGE("ReportBlockedReason parameter is nullptr");
1076 return;
1077 }
1078 if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_OFFLINE.c_str()) != NULL) {
1079 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_BLOCKED, PRINT_JOB_BLOCKED_OFFLINE);
1080 return;
1081 }
1082 if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_PAUSED.c_str()) != NULL) {
1083 param->serviceAbility->UpdatePrintJobState(
1084 param->serviceJobId, PRINT_JOB_BLOCKED, PRINT_JOB_BLOCKED_SERVICE_REQUEST);
1085 return;
1086 }
1087
1088 uint32_t substate = GetBlockedSubstate(jobStatus);
1089 if (substate > PRINT_JOB_COMPLETED_SUCCESS) {
1090 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_BLOCKED,
1091 substate);
1092 } else if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_MEDIA_NEEDED.c_str()) != NULL) {
1093 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_RUNNING,
1094 PRINT_JOB_BLOCKED_BUSY);
1095 } else {
1096 param->serviceAbility->UpdatePrintJobState(param->serviceJobId, PRINT_JOB_BLOCKED,
1097 PRINT_JOB_BLOCKED_UNKNOWN);
1098 }
1099 }
1100
GetBlockedSubstate(JobStatus * jobStatus)1101 uint32_t PrintCupsClient::GetBlockedSubstate(JobStatus *jobStatus)
1102 {
1103 uint32_t substate = PRINT_JOB_COMPLETED_SUCCESS;
1104 if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_MEDIA_EMPTY.c_str()) != NULL) {
1105 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_OUT_OF_PAPER;
1106 }
1107 if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_MEDIA_JAM.c_str()) != NULL) {
1108 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_JAMMED;
1109 }
1110 if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_TONER_EMPTY.c_str()) != NULL) {
1111 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_OUT_OF_TONER;
1112 } else if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_TONER_LOW.c_str()) != NULL) {
1113 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_LOW_ON_TONER;
1114 }
1115 if ((strstr(jobStatus->printer_state_reasons, PRINTER_STATE_MARKER_EMPTY.c_str()) != NULL) ||
1116 (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_INK_EMPTY.c_str()) != NULL)) {
1117 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_OUT_OF_INK;
1118 } else if (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_MARKER_LOW.c_str()) != NULL) {
1119 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_LOW_ON_INK;
1120 }
1121 if ((strstr(jobStatus->printer_state_reasons, PRINTER_STATE_DOOR_EMPTY.c_str()) != NULL) ||
1122 (strstr(jobStatus->printer_state_reasons, PRINTER_STATE_COVER_OPEN.c_str()) != NULL)) {
1123 substate = substate * NUMBER_FOR_SPLICING_SUBSTATE + PRINT_JOB_BLOCKED_DOOR_OPEN;
1124 }
1125 return substate;
1126 }
1127
QueryJobState(http_t * http,JobMonitorParam * param,JobStatus * jobStatus)1128 void PrintCupsClient::QueryJobState(http_t *http, JobMonitorParam *param, JobStatus *jobStatus)
1129 {
1130 ipp_t *request; /* IPP request */
1131 ipp_t *response; /* IPP response */
1132 ipp_attribute_t *attr; /* Attribute in response */
1133 int jattrsLen = 3;
1134 static const char * const jattrs[] = {
1135 "job-state",
1136 "job-state-reasons",
1137 "job-printer-state-reasons"
1138 };
1139 if (param->cupsJobId > 0) {
1140 request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES);
1141 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, param->printerUri.c_str());
1142 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", param->cupsJobId);
1143 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, DEFAULT_USER.c_str());
1144 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", jattrsLen, NULL, jattrs);
1145 PRINT_HILOGD("get job state from cups service: start");
1146 response = cupsDoRequest(http, request, "/");
1147 if ((attr = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL) {
1148 jobStatus->job_state = (ipp_jstate_t)ippGetInteger(attr, 0);
1149 }
1150 if ((attr = ippFindAttribute(response, "job-state-reasons", IPP_TAG_KEYWORD)) != NULL) {
1151 ippAttributeString(attr, jobStatus->job_state_reasons, sizeof(jobStatus->job_state_reasons));
1152 }
1153 if ((attr = ippFindAttribute(response, "job-printer-state-reasons", IPP_TAG_KEYWORD)) != NULL) {
1154 ippAttributeString(attr, jobStatus->printer_state_reasons, sizeof(jobStatus->printer_state_reasons));
1155 }
1156 PRINT_HILOGE("JOB %{public}d: %{public}s (%{public}s), PRINTER: %{public}s\n", param->cupsJobId,
1157 ippEnumString("job-state", (int)jobStatus->job_state), jobStatus->job_state_reasons,
1158 jobStatus->printer_state_reasons);
1159 ippDelete(response);
1160 }
1161 }
1162
CheckPrinterOnline(JobMonitorParam * param,const uint32_t timeout)1163 bool PrintCupsClient::CheckPrinterOnline(JobMonitorParam *param, const uint32_t timeout)
1164 {
1165 http_t *http;
1166 char scheme[32] = {0};
1167 char userpass[BUFFER_LEN] = {0};
1168 char host[BUFFER_LEN] = {0};
1169 char resource[BUFFER_LEN] = {0};
1170 int port;
1171 if (param == nullptr) {
1172 PRINT_HILOGE("param is null");
1173 return false;
1174 }
1175 const char* printerUri = param->printerUri.c_str();
1176 const std::string printerId = param->printerId;
1177 PRINT_HILOGD("CheckPrinterOnline printerId: %{public}s", printerId.c_str());
1178 httpSeparateURI(HTTP_URI_CODING_ALL, printerUri, scheme, sizeof(scheme), userpass, sizeof(userpass), host,
1179 sizeof(host), &port, resource, sizeof(resource));
1180 std::string nic;
1181 if (IsIpConflict(printerId, nic)) {
1182 http = httpConnect3(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, timeout, NULL,
1183 nic.c_str());
1184 } else {
1185 http = httpConnect2(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, timeout, NULL);
1186 }
1187 if (http == nullptr) {
1188 PRINT_HILOGE("httpConnect2 printer failed");
1189 return false;
1190 }
1191 httpClose(http);
1192 return true;
1193 }
1194
CancelCupsJob(std::string serviceJobId)1195 void PrintCupsClient::CancelCupsJob(std::string serviceJobId)
1196 {
1197 PRINT_HILOGD("CancelCupsJob(): Enter, serviceJobId: %{public}s", serviceJobId.c_str());
1198 int jobIndex = -1;
1199 for (int index = 0; index < static_cast<int>(jobQueue_.size()); index++) {
1200 PRINT_HILOGD("jobQueue_[index]->serviceJobId: %{public}s", jobQueue_[index]->serviceJobId.c_str());
1201 if (jobQueue_[index]->serviceJobId == serviceJobId) {
1202 jobIndex = index;
1203 break;
1204 }
1205 }
1206 PRINT_HILOGI("jobIndex: %{public}d", jobIndex);
1207 if (jobIndex >= 0) {
1208 PRINT_HILOGI("job in queue, delete");
1209 jobQueue_.erase(jobQueue_.begin() + jobIndex);
1210 PrintServiceAbility::GetInstance()->UpdatePrintJobState(serviceJobId, PRINT_JOB_COMPLETED,
1211 PRINT_JOB_COMPLETED_CANCELLED);
1212 } else {
1213 // 任务正在运行中
1214 if (currentJob_ && currentJob_->serviceJobId == serviceJobId) {
1215 PRINT_HILOGI("cancel current job");
1216 if (cupsCancelJob2(CUPS_HTTP_DEFAULT, currentJob_->printerName.c_str(),
1217 currentJob_->cupsJobId, 0) != IPP_OK) {
1218 PRINT_HILOGE("cancel Joob Error %{public}s", cupsLastErrorString());
1219 PrintServiceAbility::GetInstance()->UpdatePrintJobState(serviceJobId, PRINT_JOB_COMPLETED,
1220 PRINT_JOB_COMPLETED_CANCELLED);
1221 JobCompleteCallback();
1222 return;
1223 }
1224 } else {
1225 PRINT_HILOGI("job is not exist");
1226 PrintServiceAbility::GetInstance()->UpdatePrintJobState(serviceJobId, PRINT_JOB_COMPLETED,
1227 PRINT_JOB_COMPLETED_CANCELLED);
1228 }
1229 }
1230 }
1231
UpdateBorderlessJobParameter(json & optionJson,JobParameters * params)1232 static void UpdateBorderlessJobParameter(json& optionJson, JobParameters *params)
1233 {
1234 if (params == nullptr) {
1235 return;
1236 }
1237 if (optionJson.contains("documentCategory") && optionJson["documentCategory"].is_number()) {
1238 params->borderless = optionJson["documentCategory"];
1239 } else if (optionJson.contains("borderless") && optionJson["borderless"].is_string()) {
1240 std::string isBorderless = optionJson["borderless"].get<std::string>();
1241 if (isBorderless == "true") {
1242 params->borderless = 1; // 1: borderless
1243 } else {
1244 params->borderless = 0;
1245 }
1246 } else {
1247 params->borderless = 0;
1248 }
1249 }
1250
BuildJobParameters(const PrintJob & jobInfo)1251 JobParameters* PrintCupsClient::BuildJobParameters(const PrintJob &jobInfo)
1252 {
1253 JobParameters *params = nullptr;
1254 if (!jobInfo.HasOption()) {
1255 PRINT_HILOGE("option is empty");
1256 return params;
1257 }
1258 std::string option = jobInfo.GetOption();
1259 if (!json::accept(option)) {
1260 PRINT_HILOGE("option can not parse to json object");
1261 return params;
1262 }
1263 json optionJson = json::parse(option);
1264 PRINT_HILOGD("test optionJson: %{private}s", optionJson.dump().c_str());
1265 if (!optionJson.contains("printerUri") || !optionJson.contains("printerName")
1266 || !optionJson.contains("documentFormat")) {
1267 PRINT_HILOGE("The option does not have a necessary attribute.");
1268 return params;
1269 }
1270 params = new (std::nothrow) JobParameters {};
1271 jobInfo.GetFdList(params->fdList);
1272 params->serviceJobId = jobInfo.GetJobId();
1273 params->numCopies = jobInfo.GetCopyNumber();
1274 params->duplex = GetDulpexString(jobInfo.GetDuplexMode());
1275 params->jobOriginatingUserName = DEFAULT_USER;
1276 params->mediaSize = GetMedieSize(jobInfo);
1277 params->color = GetColorString(jobInfo.GetColorMode());
1278 params->printerId = jobInfo.GetPrinterId();
1279 params->printerName = PrintUtil::StandardizePrinterName(optionJson["printerName"]);
1280 params->printerUri = optionJson["printerUri"];
1281 params->documentFormat = optionJson["documentFormat"];
1282 if (optionJson.contains("cupsOptions")) {
1283 params->printerAttrsOption_cupsOption = optionJson["cupsOptions"];
1284 }
1285 UpdateBorderlessJobParameter(optionJson, params);
1286 if (optionJson.contains("printQuality") && optionJson["printQuality"].is_string()) {
1287 params->printQuality = optionJson["printQuality"].get<std::string>();
1288 } else {
1289 params->printQuality = CUPS_PRINT_QUALITY_NORMAL;
1290 }
1291 if (optionJson.contains("jobName"))
1292 params->jobName = optionJson["jobName"];
1293 else
1294 params->jobName = DEFAULT_JOB_NAME;
1295 if (optionJson.contains("mediaType")) {
1296 params->mediaType = optionJson["mediaType"];
1297 } else {
1298 params->mediaType = CUPS_MEDIA_TYPE_PLAIN;
1299 }
1300 params->serviceAbility = PrintServiceAbility::GetInstance();
1301 return params;
1302 }
1303
DumpJobParameters(JobParameters * jobParams)1304 void PrintCupsClient::DumpJobParameters(JobParameters* jobParams)
1305 {
1306 if (jobParams == nullptr) {
1307 return;
1308 }
1309 PRINT_HILOGD("jobParams->serviceJobId: %{public}s", jobParams->serviceJobId.c_str());
1310 PRINT_HILOGD("jobParams->borderless: %{public}d", jobParams->borderless);
1311 PRINT_HILOGD("jobParams->numCopies: %{public}d", jobParams->numCopies);
1312 PRINT_HILOGD("jobParams->duplex: %{public}s", jobParams->duplex.c_str());
1313 PRINT_HILOGD("jobParams->printQuality: %{public}s", jobParams->printQuality.c_str());
1314 PRINT_HILOGD("jobParams->jobName: %{public}s", jobParams->jobName.c_str());
1315 PRINT_HILOGD("jobParams->jobOriginatingUserName: %{public}s", jobParams->jobOriginatingUserName.c_str());
1316 PRINT_HILOGD("jobParams->printerId: %{private}s", jobParams->printerId.c_str());
1317 PRINT_HILOGD("jobParams->printerName: %{private}s", jobParams->printerName.c_str());
1318 PRINT_HILOGD("jobParams->printerUri: %{private}s", jobParams->printerUri.c_str());
1319 PRINT_HILOGD("jobParams->documentFormat: %{public}s", jobParams->documentFormat.c_str());
1320 PRINT_HILOGD("jobParams->mediaSize: %{public}s", jobParams->mediaSize.c_str());
1321 PRINT_HILOGD("jobParams->mediaType: %{public}s", jobParams->mediaType.c_str());
1322 PRINT_HILOGD("jobParams->color: %{public}s", jobParams->color.c_str());
1323 PRINT_HILOGD("jobParams->printerAttrsOption_cupsOption: %{public}s",
1324 jobParams->printerAttrsOption_cupsOption.c_str());
1325 }
1326
1327
GetMedieSize(const PrintJob & jobInfo)1328 std::string PrintCupsClient::GetMedieSize(const PrintJob &jobInfo)
1329 {
1330 PrintPageSize pageSize;
1331 jobInfo.GetPageSize(pageSize);
1332 return pageSize.GetName();
1333 }
1334
GetDulpexString(uint32_t duplexCode)1335 std::string PrintCupsClient::GetDulpexString(uint32_t duplexCode)
1336 {
1337 DuplexModeCode duplex = static_cast<DuplexModeCode>(duplexCode);
1338 switch (duplex) {
1339 case DUPLEX_MODE_ONE_SIDED:
1340 return CUPS_SIDES_ONE_SIDED;
1341 case DUPLEX_MODE_TWO_SIDED_LONG_EDGE:
1342 return CUPS_SIDES_TWO_SIDED_PORTRAIT;
1343 case DUPLEX_MODE_TWO_SIDED_SHORT_EDGE:
1344 return CUPS_SIDES_TWO_SIDED_LANDSCAPE;
1345 default:
1346 return CUPS_SIDES_ONE_SIDED;
1347 }
1348 }
1349
GetColorString(uint32_t colorCode)1350 std::string PrintCupsClient::GetColorString(uint32_t colorCode)
1351 {
1352 ColorModeCode color = static_cast<ColorModeCode>(colorCode);
1353 switch (color) {
1354 case COLOR_MODE_MONOCHROME:
1355 return CUPS_PRINT_COLOR_MODE_MONOCHROME;
1356 case COLOR_MODE_COLOR:
1357 return CUPS_PRINT_COLOR_MODE_COLOR;
1358 default:
1359 return CUPS_PRINT_COLOR_MODE_AUTO;
1360 }
1361 }
1362
IsCupsServerAlive()1363 bool PrintCupsClient::IsCupsServerAlive()
1364 {
1365 http_t *http;
1366 ippSetPort(CUPS_SEVER_PORT);
1367 http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, LONG_TIME_OUT, NULL);
1368 if (http == nullptr) {
1369 PRINT_HILOGE("cups server is not alive");
1370 return false;
1371 }
1372 httpClose(http);
1373 return true;
1374 }
1375
1376 /**
1377 * @brief check printer is exist
1378 * @param printerName printer name
1379 * @return true printer exist
1380 * @return false printer is not exist
1381 */
IsPrinterExist(const char * printerUri,const char * printerName,const char * ppdName)1382 bool PrintCupsClient::IsPrinterExist(const char *printerUri, const char *printerName, const char *ppdName)
1383 {
1384 bool printerExist = false;
1385 cups_dest_t *dest;
1386 PRINT_HILOGD("IsPrinterExist enter");
1387 dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printerName, NULL);
1388 if (dest != NULL) {
1389 const char *deviceUri = cupsGetOption("device-uri", dest->num_options, dest->options);
1390 PRINT_HILOGD("deviceUri=%{private}s", deviceUri);
1391 const char *makeModel = cupsGetOption("printer-make-and-model", dest->num_options, dest->options);
1392 PRINT_HILOGD("makeModel=%{private}s", makeModel);
1393 int printerState = cupsGetIntegerOption("printer-state", dest->num_options, dest->options);
1394 PRINT_HILOGD("printerState=%{private}d", printerState);
1395 if (printerState == IPP_PRINTER_STOPPED || makeModel == nullptr || strcmp(deviceUri, printerUri) != 0) {
1396 cupsFreeDests(1, dest);
1397 PRINT_HILOGI("Printer information needs to be modified");
1398 return printerExist;
1399 }
1400 if (strcmp(ppdName, DEFAULT_PPD_NAME.c_str()) == 0) {
1401 // 没查到驱动
1402 printerExist = (strstr(makeModel, DEFAULT_MAKE_MODEL.c_str()) != NULL);
1403 } else {
1404 // 查到驱动
1405 printerExist = !(strstr(makeModel, DEFAULT_MAKE_MODEL.c_str()) != NULL);
1406 if (!printerExist) {
1407 // 私有驱动已卸载,需要先删除打印机再添加,不然下发任务找不到驱动
1408 DeleteCupsPrinter(printerName);
1409 }
1410 }
1411 cupsFreeDests(1, dest);
1412 }
1413 return printerExist;
1414 }
1415
ConvertInchTo100MM(float num)1416 float PrintCupsClient::ConvertInchTo100MM(float num)
1417 {
1418 return ((num / THOUSAND_INCH) * CONVERSION_UNIT);
1419 }
1420
IsIpConflict(const std::string & printerId,std::string & nic)1421 bool PrintCupsClient::IsIpConflict(const std::string &printerId, std::string &nic) __attribute__((no_sanitize("cfi")))
1422 {
1423 if (printerId.find(P2P_PRINTER) == std::string::npos) {
1424 PRINT_HILOGD("The printer is not p2p: %{private}s", printerId.c_str());
1425 return false;
1426 }
1427 bool isWifiConnected = false;
1428 auto wifiDevice = Wifi::WifiDevice::GetInstance(OHOS::WIFI_DEVICE_SYS_ABILITY_ID);
1429 if (!wifiDevice) {
1430 PRINT_HILOGE("wifiDevice GetInstance failed.");
1431 return false;
1432 }
1433 wifiDevice->IsConnected(isWifiConnected);
1434 PRINT_HILOGD("isWifiConnected: %{public}d", isWifiConnected);
1435 Wifi::WifiP2pLinkedInfo p2pLinkedInfo;
1436 Wifi::WifiP2p::GetInstance(OHOS::WIFI_P2P_SYS_ABILITY_ID)->QueryP2pLinkedInfo(p2pLinkedInfo);
1437 PRINT_HILOGD("P2pConnectedState: %{public}d", p2pLinkedInfo.GetConnectState());
1438 if (isWifiConnected && p2pLinkedInfo.GetConnectState() == Wifi::P2pConnectedState::P2P_CONNECTED) {
1439 Wifi::IpInfo info;
1440 auto wifiDevice = Wifi::WifiDevice::GetInstance(OHOS::WIFI_DEVICE_SYS_ABILITY_ID);
1441 if (!wifiDevice) {
1442 PRINT_HILOGE("wifiDevice GetInstance failed.");
1443 return false;
1444 }
1445 wifiDevice->GetIpInfo(info);
1446 PRINT_HILOGD("wifi server ip: %{private}s", GetIpAddress(info.serverIp).c_str());
1447 PRINT_HILOGD("p2p go ip: %{private}s", p2pLinkedInfo.GetGroupOwnerAddress().c_str());
1448 if (GetIpAddress(info.serverIp) == p2pLinkedInfo.GetGroupOwnerAddress()) {
1449 Wifi::WifiP2pGroupInfo group;
1450 Wifi::WifiP2p::GetInstance(OHOS::WIFI_P2P_SYS_ABILITY_ID)->GetCurrentGroup(group);
1451 nic = group.GetInterface();
1452 PRINT_HILOGI("The P2P ip conflicts with the wlan ip, p2p nic: %{public}s", nic.c_str());
1453 return true;
1454 }
1455 }
1456 return false;
1457 }
1458
GetIpAddress(unsigned int number)1459 std::string PrintCupsClient::GetIpAddress(unsigned int number)
1460 {
1461 unsigned int ip3 = (number << IP_RIGHT_SHIFT_0) >> IP_RIGHT_SHIFT_24;
1462 unsigned int ip2 = (number << IP_RIGHT_SHIFT_8) >> IP_RIGHT_SHIFT_24;
1463 unsigned int ip1 = (number << IP_RIGHT_SHIFT_16) >> IP_RIGHT_SHIFT_24;
1464 unsigned int ip0 = (number << IP_RIGHT_SHIFT_24) >> IP_RIGHT_SHIFT_24;
1465 return std::to_string(ip3) + "." + std::to_string(ip2) + "." + std::to_string(ip1) + "." + std::to_string(ip0);
1466 }
1467 }