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 <vector>
17 #include <string>
18 
19 #include "print_cups_attribute.h"
20 #include "print_service_converter.h"
21 #include "print_log.h"
22 
23 namespace OHOS::Print {
24 template <typename T>
ParseAttributeToValue(ipp_t *response, const std::string &keyword, T &value, bool (*convertAttr)(const char *src, T &dst))25 bool ParseAttributeToValue(ipp_t *response, const std::string &keyword, T &value,
26     bool (*convertAttr)(const char *src, T &dst))
27 {
28     if (convertAttr == nullptr) {
29         PRINT_HILOGW("convertAttr is null");
30         return false;
31     }
32     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_KEYWORD);
33     if (attrPtr == nullptr) {
34         PRINT_HILOGW("attrPtr is null");
35         return false;
36     }
37     const char *attrString = ippGetString(attrPtr, 0, NULL);
38     if (attrString == nullptr) {
39         PRINT_HILOGW("attrString is null");
40         return false;
41     }
42     PRINT_HILOGD("attrString: %{public}s", attrString);
43     if (!convertAttr(attrString, value)) {
44         PRINT_HILOGW("ConvertFunction fail");
45         return false;
46     }
47     return true;
48 }
49 
50 template <typename T>
ParseAttributesToList(ipp_t *response, const std::string &keyword, std::vector<T> &list, bool (*convertAttr)(const char *src, T &dst))51 bool ParseAttributesToList(ipp_t *response, const std::string &keyword, std::vector<T> &list,
52     bool (*convertAttr)(const char *src, T &dst))
53 {
54     if (convertAttr == nullptr) {
55         PRINT_HILOGW("convertAttr is null");
56         return false;
57     }
58     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_KEYWORD);
59     if (attrPtr == nullptr) {
60         PRINT_HILOGW("attrPtr is null");
61         return false;
62     }
63     int num = ippGetCount(attrPtr);
64     PRINT_HILOGD("number of values %{public}d", num);
65     for (int i = 0; i < num; i++) {
66         const char *attrString = ippGetString(attrPtr, i, NULL);
67         if (attrString == nullptr) {
68             PRINT_HILOGW("attrString is null");
69             continue;
70         }
71         PRINT_HILOGD("attrString: %{public}s", attrString);
72         T attrValue;
73         if (!convertAttr(attrString, attrValue)) {
74             PRINT_HILOGW("ConvertFunction fail");
75             continue;
76         }
77         AddToUniqueList<T>(list, attrValue);
78     }
79     return true;
80 }
81 
ConvertDuplexModeCode(const char *src, DuplexModeCode &dst)82 bool ConvertDuplexModeCode(const char *src, DuplexModeCode &dst)
83 {
84     if (src == nullptr) {
85         return false;
86     }
87     if (strcasestr(src, CUPS_SIDES_ONE_SIDED)) {
88         dst = DUPLEX_MODE_ONE_SIDED;
89     } else if (strcasestr(src, CUPS_SIDES_TWO_SIDED_PORTRAIT)) {
90         dst = DUPLEX_MODE_TWO_SIDED_LONG_EDGE;
91     } else if (strcasestr(src, CUPS_SIDES_TWO_SIDED_LANDSCAPE)) {
92         dst = DUPLEX_MODE_TWO_SIDED_SHORT_EDGE;
93     } else {
94         return false;
95     }
96     return true;
97 }
98 
ConvertIppAttributesToJsonString(ipp_t *response, const std::string &keyword)99 std::string ConvertIppAttributesToJsonString(ipp_t *response, const std::string &keyword)
100 {
101     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_KEYWORD);
102     if (attrPtr == nullptr) {
103         return "";
104     }
105     nlohmann::json jsonArray = nlohmann::json::array();
106     for (int i = 0; i < ippGetCount(attrPtr); i++) {
107         const char *attrString = ippGetString(attrPtr, i, NULL);
108         if (attrString == nullptr) {
109             continue;
110         }
111         jsonArray.push_back(attrString);
112     }
113     return jsonArray.dump();
114 }
115 
SetCapabilityGroupAttribute(ipp_t *response, PrinterCapability &printerCaps)116 void SetCapabilityGroupAttribute(ipp_t *response, PrinterCapability &printerCaps)
117 {
118     ipp_attribute_t *attrPtr;
119     if ((attrPtr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
120         printerCaps.SetPrinterAttrNameAndValue("printer-state",
121             ippEnumString("printer-state", ippGetInteger(attrPtr, 0)));
122     }
123     if ((attrPtr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXTLANG)) != NULL) {
124         printerCaps.SetPrinterAttrNameAndValue("printer-info", ippGetString(attrPtr, 0, NULL));
125     }
126     if ((attrPtr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT)) != NULL) {
127         printerCaps.SetPrinterAttrNameAndValue("printer-location", ippGetString(attrPtr, 0, NULL));
128     }
129 }
130 
ParseDuplexModeAttributes(ipp_t *response, PrinterCapability &printerCaps)131 void ParseDuplexModeAttributes(ipp_t *response, PrinterCapability &printerCaps)
132 {
133     std::string keyword = "sides-supported";
134     std::vector<DuplexModeCode> list;
135     ParseAttributesToList(response, keyword, list, ConvertDuplexModeCode);
136     std::string duplexModeJson = ConvertListToJson<DuplexModeCode>(list, ConvertDuplexModeToJson);
137     printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), duplexModeJson.c_str());
138     size_t num = list.size();
139     if (static_cast<int>(num) <= 1) {
140         printerCaps.SetDuplexMode((uint32_t)DUPLEX_MODE_ONE_SIDED);
141     } else {
142         printerCaps.SetDuplexMode((uint32_t)DUPLEX_MODE_TWO_SIDED_LONG_EDGE);
143     }
144     printerCaps.SetSupportedDuplexMode(std::vector<uint32_t>(list.begin(), list.end()));
145 
146     keyword = "sides-default";
147     DuplexModeCode code;
148     if (ParseAttributeToValue<DuplexModeCode>(response, keyword, code, ConvertDuplexModeCode)) {
149         uint32_t value = static_cast<uint32_t>(code);
150         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), std::to_string(value).c_str());
151     }
152 }
153 
ParseColorModeAttributes(ipp_t *response, PrinterCapability &printerCaps)154 void ParseColorModeAttributes(ipp_t *response, PrinterCapability &printerCaps)
155 {
156     std::string keyword = "print-color-mode-supported";
157     std::vector<ColorModeCode> supportedColorModes;
158     ParseAttributesToList<ColorModeCode>(response, keyword, supportedColorModes, ConvertColorModeCode);
159     std::string colorModeJson = ConvertListToJson<ColorModeCode>(supportedColorModes, ConvertColorModeToJson);
160     printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), colorModeJson.c_str());
161 
162     keyword = "print-color-mode-default";
163     ColorModeCode code;
164     if (ParseAttributeToValue<ColorModeCode>(response, keyword, code, ConvertColorModeCode)) {
165         uint32_t mode = static_cast<uint32_t>(code);
166         printerCaps.SetPrinterAttrNameAndValue("defaultColorMode", std::to_string(mode).c_str());
167     }
168     for (auto& color : supportedColorModes) {
169         if (color == ColorModeCode::COLOR_MODE_COLOR) {
170             printerCaps.SetColorMode(ColorModeCode::COLOR_MODE_COLOR);
171             break;
172         }
173     }
174     printerCaps.SetSupportedColorMode(std::vector<uint32_t>(supportedColorModes.begin(), supportedColorModes.end()));
175 }
176 
ParsePageSizeAttributes(ipp_t *response, PrinterCapability &printerCaps)177 void ParsePageSizeAttributes(ipp_t *response, PrinterCapability &printerCaps)
178 {
179     std::string keyword = "media-supported";
180     std::vector<PrintPageSize> supportedPageSizes;
181     ParseAttributesToList<PrintPageSize>(response, keyword, supportedPageSizes, ConvertPrintPageSize);
182     std::string pageSizeJson = ConvertListToJson<PrintPageSize>(supportedPageSizes, ConvertPageSizeToJson);
183     printerCaps.SetSupportedPageSize(supportedPageSizes);
184     printerCaps.SetPrinterAttrNameAndValue("supportedPageSizeArray", pageSizeJson.c_str());
185 
186     std::string defaultPageSizeId;
187     keyword = "media-default";
188     if (ParseAttributeToValue<std::string>(response, keyword, defaultPageSizeId, ConvertPageSizeId)) {
189         printerCaps.SetPrinterAttrNameAndValue("defaultPageSizeId", defaultPageSizeId.c_str());
190     }
191 }
192 
ParseQualityAttributes(ipp_t *response, PrinterCapability &printerCaps)193 void ParseQualityAttributes(ipp_t *response, PrinterCapability &printerCaps)
194 {
195     std::string keyword = "print-quality-supported";
196     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ENUM);
197     if (attrPtr == nullptr) {
198         PRINT_HILOGW("%{public}s missing", keyword.c_str());
199         return;
200     }
201     nlohmann::json supportedQualities = nlohmann::json::array();
202     std::vector<uint32_t> list;
203     for (int i = 0; i < ippGetCount(attrPtr); i++) {
204         nlohmann::json jsonObject;
205         int quality = ippGetInteger(attrPtr, i);
206         if (quality < 0) {
207             PRINT_HILOGE("%{public}s meet error quality", keyword.c_str());
208             continue;
209         }
210         uint32_t value = static_cast<uint32_t>(quality);
211         jsonObject["quality"] = value;
212         supportedQualities.push_back(jsonObject);
213         list.emplace_back(value);
214     }
215     std::string attrString = supportedQualities.dump();
216     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), attrString.c_str());
217     printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), attrString.c_str());
218     printerCaps.SetSupportedQuality(list);
219 }
220 
ParseCopiesAttributes(ipp_t *response, PrinterCapability &printerCaps)221 void ParseCopiesAttributes(ipp_t *response, PrinterCapability &printerCaps)
222 {
223     ipp_attribute_t *attrPtr = ippFindAttribute(response, "copies-supported", IPP_TAG_RANGE);
224     if (attrPtr != nullptr) {
225         int upper = 0;
226         for (int i = 0; i < ippGetCount(attrPtr); i++) {
227             ippGetRange(attrPtr, i, &upper);
228         }
229         printerCaps.SetPrinterAttrNameAndValue("copies-supported", std::to_string(upper).c_str());
230     }
231     attrPtr = ippFindAttribute(response, "copies-default", IPP_TAG_INTEGER);
232     if (attrPtr != nullptr) {
233         printerCaps.SetPrinterAttrNameAndValue("copies-default", std::to_string(ippGetInteger(attrPtr, 0)).c_str());
234     }
235 }
236 
ParseSupportedResolutionAttribute(ipp_t *response, PrinterCapability &printerCaps)237 void ParseSupportedResolutionAttribute(ipp_t *response, PrinterCapability &printerCaps)
238 {
239     std::string keyword = "printer-resolution-supported";
240     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_RESOLUTION);
241     if (attrPtr == nullptr) {
242         PRINT_HILOGW("attrPtr is null");
243         return;
244     }
245     int num = ippGetCount(attrPtr);
246     PRINT_HILOGD("number of values %{public}d", num);
247     nlohmann::json resolutionArray = nlohmann::json::array();
248     std::vector<PrintResolution> list;
249     for (int i = 0; i < num; i++) {
250         ipp_res_t units = IPP_RES_PER_INCH;
251         int xres = 0;
252         int yres = 0;
253         xres = ippGetResolution(attrPtr, i, &yres, &units);
254         if (xres == 0 || yres == 0) {
255             continue;
256         }
257         if (units == IPP_RES_PER_CM) {
258             xres = DpcToDpi(xres);
259             yres = DpcToDpi(yres);
260         } else if (units != IPP_RES_PER_INCH) {
261             PRINT_HILOGW("unknown dpi unit: %{public}d", static_cast<int>(units));
262             continue;
263         }
264         nlohmann::json object;
265         object["horizontalDpi"] = xres;
266         object["verticalDpi"] = yres;
267         PrintResolution printResolution;
268         printResolution.SetHorizontalDpi(xres);
269         printResolution.SetVerticalDpi(yres);
270         list.emplace_back(printResolution);
271         resolutionArray.push_back(object);
272     }
273     printerCaps.SetResolution(list);
274     printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), resolutionArray.dump().c_str());
275 }
276 
ParseDefaultResolutionAttribute(ipp_t *response, PrinterCapability &printerCaps)277 void ParseDefaultResolutionAttribute(ipp_t *response, PrinterCapability &printerCaps)
278 {
279     std::string keyword = "printer-resolution-default";
280     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_RESOLUTION);
281     if (attrPtr == nullptr) {
282         PRINT_HILOGW("attrPtr is null");
283         return;
284     }
285     int num = ippGetCount(attrPtr);
286     PRINT_HILOGD("number of values %{public}d", num);
287     for (int i = 0; i < num; i++) {
288         ipp_res_t units = IPP_RES_PER_INCH;
289         int xres = 0;
290         int yres = 0;
291         xres = ippGetResolution(attrPtr, i, &yres, &units);
292         if (xres == 0 || yres == 0) {
293             continue;
294         }
295         if (units == IPP_RES_PER_CM) {
296             xres = DpcToDpi(xres);
297             yres = DpcToDpi(yres);
298         } else if (units != IPP_RES_PER_INCH) {
299             PRINT_HILOGW("unknown dpi unit: %{public}d", static_cast<int>(units));
300             continue;
301         }
302         nlohmann::json object;
303         object["horizontalDpi"] = xres;
304         object["verticalDpi"] = yres;
305         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), object.dump().c_str());
306         break;
307     }
308 }
309 
ParseMediaColDefaultAttributes(ipp_t *response, PrinterCapability &printerCaps)310 void ParseMediaColDefaultAttributes(ipp_t *response, PrinterCapability &printerCaps)
311 {
312     ipp_attribute_t *defaultMediaPtr = ippFindAttribute(response, "media-col-default", IPP_TAG_BEGIN_COLLECTION);
313     if (defaultMediaPtr == nullptr) {
314         PRINT_HILOGW("media-col-default missing");
315         return;
316     }
317     ipp_t *defaultMediaCol = defaultMediaPtr->values[0].collection;
318     if (defaultMediaCol == nullptr) {
319         PRINT_HILOGW("defaultMediaCol is null");
320         return;
321     }
322     std::vector<std::string> keywordList;
323     keywordList.push_back("media-top-margin");
324     keywordList.push_back("media-bottom-margin");
325     keywordList.push_back("media-left-margin");
326     keywordList.push_back("media-right-margin");
327     for (auto &keyword : keywordList) {
328         ipp_attribute_t *attrPtr = ippFindAttribute(defaultMediaCol, keyword.c_str(), IPP_TAG_INTEGER);
329         if (attrPtr != nullptr) {
330             int value = ippGetInteger(attrPtr, 0);
331             PRINT_HILOGD("%{public}s found: %{public}d", keyword.c_str(), value);
332             std::string defaultKeyword = keyword + "-default";
333             printerCaps.SetPrinterAttrNameAndValue(defaultKeyword.c_str(), std::to_string(value).c_str());
334         }
335     }
336     ipp_attribute_t *attrPtr = ippFindAttribute(defaultMediaCol, "duplex-supported", IPP_TAG_BOOLEAN);
337     if (attrPtr != nullptr) {
338         PRINT_HILOGD("duplex-supported found: %{public}d", ippGetBoolean(attrPtr, 0));
339     }
340     attrPtr = ippFindAttribute(defaultMediaCol, "media-source", IPP_TAG_KEYWORD);
341     if (attrPtr != nullptr) {
342         PRINT_HILOGD("media-source-default found: %{public}s", ippGetString(attrPtr, 0, NULL));
343         printerCaps.SetPrinterAttrNameAndValue("media-source-default", ippGetString(attrPtr, 0, NULL));
344     }
345     attrPtr = ippFindAttribute(defaultMediaCol, "media-type", IPP_TAG_KEYWORD);
346     if (attrPtr != nullptr) {
347         PRINT_HILOGD("media-type-default found: %{public}s", ippGetString(attrPtr, 0, NULL));
348         printerCaps.SetPrinterAttrNameAndValue("media-type-default", ippGetString(attrPtr, 0, NULL));
349     }
350 }
351 
ParseMediaMarginAttributes(ipp_t *response, PrinterCapability &printerCaps)352 void ParseMediaMarginAttributes(ipp_t *response, PrinterCapability &printerCaps)
353 {
354     ipp_attribute_t *attrPtr;
355     if ((attrPtr = ippFindAttribute(response, "media-bottom-margin-supported", IPP_TAG_INTEGER)) != NULL) {
356         printerCaps.SetPrinterAttrNameAndValue("media-bottom-margin-supported",
357             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
358     }
359     if ((attrPtr = ippFindAttribute(response, "media-top-margin-supported", IPP_TAG_INTEGER)) != NULL) {
360         printerCaps.SetPrinterAttrNameAndValue("media-top-margin-supported",
361             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
362     }
363     if ((attrPtr = ippFindAttribute(response, "media-left-margin-supported", IPP_TAG_INTEGER)) != NULL) {
364         printerCaps.SetPrinterAttrNameAndValue("media-left-margin-supported",
365             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
366     }
367     if ((attrPtr = ippFindAttribute(response, "media-right-margin-supported", IPP_TAG_INTEGER)) != NULL) {
368         printerCaps.SetPrinterAttrNameAndValue("media-right-margin-supported",
369             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
370     }
371 }
372 
ParseOrientationAttributes(ipp_t *response, PrinterCapability &printerCaps)373 void ParseOrientationAttributes(ipp_t *response, PrinterCapability &printerCaps)
374 {
375     std::string keyword = "orientation-requested-default";
376     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ENUM);
377     if (attrPtr != NULL) {
378         int orientationEnum = ippGetInteger(attrPtr, 0);
379         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), std::to_string(orientationEnum).c_str());
380         PRINT_HILOGD("orientation-default found: %{public}d", orientationEnum);
381     }
382     keyword = "orientation-requested-supported";
383     attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ENUM);
384     if (attrPtr != NULL) {
385         int num = ippGetCount(attrPtr);
386         if (num > 0) {
387             nlohmann::json supportedOrientationArray = nlohmann::json::array();
388             std::vector<uint32_t> supportedOrientations;
389             supportedOrientations.reserve(num);
390             for (int i = 0; i < ippGetCount(attrPtr); i++) {
391                 int orientationEnum = ippGetInteger(attrPtr, i);
392                 supportedOrientationArray.push_back(orientationEnum);
393                 supportedOrientations.emplace_back(orientationEnum);
394                 PRINT_HILOGD("orientation-supported found: %{public}d", orientationEnum);
395             }
396             printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), supportedOrientationArray.dump().c_str());
397             printerCaps.SetSupportedOrientation(supportedOrientations);
398         }
399     }
400 }
401 
ParseOtherAttributes(ipp_t *response, PrinterCapability &printerCaps)402 void ParseOtherAttributes(ipp_t *response, PrinterCapability &printerCaps)
403 {
404     std::string keyword = "media-source-supported";
405     std::string attrString = ConvertIppAttributesToJsonString(response, keyword);
406     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), attrString.c_str());
407     if (!attrString.empty()) {
408         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), attrString.c_str());
409     }
410 
411     keyword = "multiple-document-handling-supported";
412     attrString = ConvertIppAttributesToJsonString(response, keyword);
413     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), attrString.c_str());
414     if (!attrString.empty()) {
415         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), attrString.c_str());
416     }
417 }
418 
SetOptionAttribute(ipp_t *response, PrinterCapability &printerCaps)419 void SetOptionAttribute(ipp_t *response, PrinterCapability &printerCaps)
420 {
421     ipp_attribute_t *attrPtr;
422     nlohmann::json options;
423     if ((attrPtr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT)) != NULL) {
424         options["make"] = ippGetString(attrPtr, 0, NULL);
425     }
426     if ((attrPtr = ippFindAttribute(response, "printer-uuid", IPP_TAG_URI)) != NULL) {
427         options["uuid"] = ippGetString(attrPtr, 0, NULL);
428     }
429     if ((attrPtr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) {
430         options["printerName"] = ippGetString(attrPtr, 0, NULL);
431     }
432     std::string keyword = "media-type-supported";
433     std::string supportTypes;
434     std::vector<std::string> list;
435     attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ZERO);
436     if (attrPtr == nullptr) {
437         supportTypes = "";
438     } else {
439         nlohmann::json jsonArray = nlohmann::json::array();
440         for (int i = 0; i < ippGetCount(attrPtr); i++) {
441             const char *attrString = ippGetString(attrPtr, i, NULL);
442             if (attrString == nullptr) {
443                 continue;
444             }
445             jsonArray.push_back(attrString);
446             list.emplace_back(attrString);
447         }
448         supportTypes = jsonArray.dump();
449     }
450     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), supportTypes.c_str());
451     if (!supportTypes.empty()) {
452         printerCaps.SetSupportedMediaType(list);
453         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), supportTypes.c_str());
454     }
455 
456     nlohmann::json cupsOptionsJson = printerCaps.GetPrinterAttrGroupJson();
457     options["cupsOptions"] = cupsOptionsJson;
458 
459     std::string optionStr = options.dump();
460     PRINT_HILOGD("SetOption: %{public}s", optionStr.c_str());
461     printerCaps.SetOption(optionStr);
462 }
463 
ParsePrinterAttributes(ipp_t *response, PrinterCapability &printerCaps)464 void ParsePrinterAttributes(ipp_t *response, PrinterCapability &printerCaps)
465 {
466     SetCapabilityGroupAttribute(response, printerCaps);
467     ParseColorModeAttributes(response, printerCaps);
468     ParseDuplexModeAttributes(response, printerCaps);
469     ParsePageSizeAttributes(response, printerCaps);
470     ParseQualityAttributes(response, printerCaps);
471     ParseSupportedResolutionAttribute(response, printerCaps);
472     ParseDefaultResolutionAttribute(response, printerCaps);
473     ParseMediaColDefaultAttributes(response, printerCaps);
474     ParseMediaMarginAttributes(response, printerCaps);
475     ParseOrientationAttributes(response, printerCaps);
476     ParseCopiesAttributes(response, printerCaps);
477     ParseOtherAttributes(response, printerCaps);
478     SetOptionAttribute(response, printerCaps);
479 }
480 
ParsePrinterStatusAttributes(ipp_t *response, PrinterStatus &status)481 bool ParsePrinterStatusAttributes(ipp_t *response, PrinterStatus &status)
482 {
483     ipp_attribute_t *attrPtr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM);
484     if (attrPtr != NULL) {
485         int enumValue = ippGetInteger(attrPtr, 0) - IPP_PSTATE_IDLE;
486         if (enumValue >= PRINTER_STATUS_IDLE && enumValue <= PRINTER_STATUS_UNAVAILABLE) {
487             status = static_cast<PrinterStatus>(enumValue);
488             return true;
489         }
490     }
491     return false;
492 }
493 }  // namespace OHOS::Print