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, nullptr);
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, nullptr);
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, nullptr);
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)) != nullptr) {
120         printerCaps.SetPrinterAttrNameAndValue("printer-state",
121             ippEnumString("printer-state", ippGetInteger(attrPtr, 0)));
122     }
123     if ((attrPtr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXTLANG)) != nullptr) {
124         printerCaps.SetPrinterAttrNameAndValue("printer-info", ippGetString(attrPtr, 0, nullptr));
125     }
126     if ((attrPtr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT)) != nullptr) {
127         printerCaps.SetPrinterAttrNameAndValue("printer-location", ippGetString(attrPtr, 0, nullptr));
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     printerCaps.SetSupportedPageSize(supportedPageSizes);
183 
184     std::string defaultPageSizeId;
185     keyword = "media-default";
186     if (ParseAttributeToValue<std::string>(response, keyword, defaultPageSizeId, ConvertPageSizeId)) {
187         printerCaps.SetPrinterAttrNameAndValue("defaultPageSizeId", defaultPageSizeId.c_str());
188     }
189 }
190 
ParseQualityAttributes(ipp_t * response,PrinterCapability & printerCaps)191 void ParseQualityAttributes(ipp_t *response, PrinterCapability &printerCaps)
192 {
193     std::string keyword = "print-quality-supported";
194     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ENUM);
195     if (attrPtr == nullptr) {
196         PRINT_HILOGW("%{public}s missing", keyword.c_str());
197         return;
198     }
199     nlohmann::json supportedQualities = nlohmann::json::array();
200     std::vector<uint32_t> list;
201     for (int i = 0; i < ippGetCount(attrPtr); i++) {
202         nlohmann::json jsonObject;
203         int quality = ippGetInteger(attrPtr, i);
204         if (quality < 0) {
205             PRINT_HILOGE("%{public}s meet error quality", keyword.c_str());
206             continue;
207         }
208         uint32_t value = static_cast<uint32_t>(quality);
209         jsonObject["quality"] = value;
210         supportedQualities.push_back(jsonObject);
211         list.emplace_back(value);
212     }
213     std::string attrString = supportedQualities.dump();
214     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), attrString.c_str());
215     printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), attrString.c_str());
216     printerCaps.SetSupportedQuality(list);
217 }
218 
ParseCopiesAttributes(ipp_t * response,PrinterCapability & printerCaps)219 void ParseCopiesAttributes(ipp_t *response, PrinterCapability &printerCaps)
220 {
221     ipp_attribute_t *attrPtr = ippFindAttribute(response, "copies-supported", IPP_TAG_RANGE);
222     if (attrPtr != nullptr) {
223         int upper = 0;
224         for (int i = 0; i < ippGetCount(attrPtr); i++) {
225             ippGetRange(attrPtr, i, &upper);
226         }
227         printerCaps.SetPrinterAttrNameAndValue("copies-supported", std::to_string(upper).c_str());
228     }
229     attrPtr = ippFindAttribute(response, "copies-default", IPP_TAG_INTEGER);
230     if (attrPtr != nullptr) {
231         printerCaps.SetPrinterAttrNameAndValue("copies-default", std::to_string(ippGetInteger(attrPtr, 0)).c_str());
232     }
233 }
234 
ParseSupportedResolutionAttribute(ipp_t * response,PrinterCapability & printerCaps)235 void ParseSupportedResolutionAttribute(ipp_t *response, PrinterCapability &printerCaps)
236 {
237     std::string keyword = "printer-resolution-supported";
238     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_RESOLUTION);
239     if (attrPtr == nullptr) {
240         PRINT_HILOGW("attrPtr is null");
241         return;
242     }
243     int num = ippGetCount(attrPtr);
244     PRINT_HILOGD("number of values %{public}d", num);
245     nlohmann::json resolutionArray = nlohmann::json::array();
246     std::vector<PrintResolution> list;
247     for (int i = 0; i < num; i++) {
248         ipp_res_t units = IPP_RES_PER_INCH;
249         int xres = 0;
250         int yres = 0;
251         xres = ippGetResolution(attrPtr, i, &yres, &units);
252         if (xres == 0 || yres == 0) {
253             continue;
254         }
255         if (units == IPP_RES_PER_CM) {
256             xres = DpcToDpi(xres);
257             yres = DpcToDpi(yres);
258         } else if (units != IPP_RES_PER_INCH) {
259             PRINT_HILOGW("unknown dpi unit: %{public}d", static_cast<int>(units));
260             continue;
261         }
262         nlohmann::json object;
263         object["horizontalDpi"] = xres;
264         object["verticalDpi"] = yres;
265         PrintResolution printResolution;
266         printResolution.SetHorizontalDpi(xres);
267         printResolution.SetVerticalDpi(yres);
268         list.emplace_back(printResolution);
269         resolutionArray.push_back(object);
270     }
271     printerCaps.SetResolution(list);
272     printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), resolutionArray.dump().c_str());
273 }
274 
ParseDefaultResolutionAttribute(ipp_t * response,PrinterCapability & printerCaps)275 void ParseDefaultResolutionAttribute(ipp_t *response, PrinterCapability &printerCaps)
276 {
277     std::string keyword = "printer-resolution-default";
278     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_RESOLUTION);
279     if (attrPtr == nullptr) {
280         PRINT_HILOGW("attrPtr is null");
281         return;
282     }
283     int num = ippGetCount(attrPtr);
284     PRINT_HILOGD("number of values %{public}d", num);
285     for (int i = 0; i < num; i++) {
286         ipp_res_t units = IPP_RES_PER_INCH;
287         int xres = 0;
288         int yres = 0;
289         xres = ippGetResolution(attrPtr, i, &yres, &units);
290         if (xres == 0 || yres == 0) {
291             continue;
292         }
293         if (units == IPP_RES_PER_CM) {
294             xres = DpcToDpi(xres);
295             yres = DpcToDpi(yres);
296         } else if (units != IPP_RES_PER_INCH) {
297             PRINT_HILOGW("unknown dpi unit: %{public}d", static_cast<int>(units));
298             continue;
299         }
300         nlohmann::json object;
301         object["horizontalDpi"] = xres;
302         object["verticalDpi"] = yres;
303         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), object.dump().c_str());
304         break;
305     }
306 }
307 
ParseMediaColDefaultAttributes(ipp_t * response,PrinterCapability & printerCaps)308 void ParseMediaColDefaultAttributes(ipp_t *response, PrinterCapability &printerCaps)
309 {
310     ipp_attribute_t *defaultMediaPtr = ippFindAttribute(response, "media-col-default", IPP_TAG_BEGIN_COLLECTION);
311     if (defaultMediaPtr == nullptr) {
312         PRINT_HILOGW("media-col-default missing");
313         return;
314     }
315     ipp_t *defaultMediaCol = defaultMediaPtr->values[0].collection;
316     if (defaultMediaCol == nullptr) {
317         PRINT_HILOGW("defaultMediaCol is null");
318         return;
319     }
320     std::vector<std::string> keywordList;
321     keywordList.push_back("media-top-margin");
322     keywordList.push_back("media-bottom-margin");
323     keywordList.push_back("media-left-margin");
324     keywordList.push_back("media-right-margin");
325     for (auto &keyword : keywordList) {
326         ipp_attribute_t *attrPtr = ippFindAttribute(defaultMediaCol, keyword.c_str(), IPP_TAG_INTEGER);
327         if (attrPtr != nullptr) {
328             int value = ippGetInteger(attrPtr, 0);
329             PRINT_HILOGD("%{public}s found: %{public}d", keyword.c_str(), value);
330             std::string defaultKeyword = keyword + "-default";
331             printerCaps.SetPrinterAttrNameAndValue(defaultKeyword.c_str(), std::to_string(value).c_str());
332         }
333     }
334     ipp_attribute_t *attrPtr = ippFindAttribute(defaultMediaCol, "duplex-supported", IPP_TAG_BOOLEAN);
335     if (attrPtr != nullptr) {
336         PRINT_HILOGD("duplex-supported found: %{public}d", ippGetBoolean(attrPtr, 0));
337     }
338     attrPtr = ippFindAttribute(defaultMediaCol, "media-source", IPP_TAG_KEYWORD);
339     if (attrPtr != nullptr) {
340         PRINT_HILOGD("media-source-default found: %{public}s", ippGetString(attrPtr, 0, nullptr));
341         printerCaps.SetPrinterAttrNameAndValue("media-source-default", ippGetString(attrPtr, 0, nullptr));
342     }
343     attrPtr = ippFindAttribute(defaultMediaCol, "media-type", IPP_TAG_KEYWORD);
344     if (attrPtr != nullptr) {
345         PRINT_HILOGD("media-type-default found: %{public}s", ippGetString(attrPtr, 0, nullptr));
346         printerCaps.SetPrinterAttrNameAndValue("media-type-default", ippGetString(attrPtr, 0, nullptr));
347     }
348 }
349 
ParseMediaMarginAttributes(ipp_t * response,PrinterCapability & printerCaps)350 void ParseMediaMarginAttributes(ipp_t *response, PrinterCapability &printerCaps)
351 {
352     ipp_attribute_t *attrPtr;
353     if ((attrPtr = ippFindAttribute(response, "media-bottom-margin-supported", IPP_TAG_INTEGER)) != nullptr) {
354         printerCaps.SetPrinterAttrNameAndValue("media-bottom-margin-supported",
355             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
356     }
357     if ((attrPtr = ippFindAttribute(response, "media-top-margin-supported", IPP_TAG_INTEGER)) != nullptr) {
358         printerCaps.SetPrinterAttrNameAndValue("media-top-margin-supported",
359             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
360     }
361     if ((attrPtr = ippFindAttribute(response, "media-left-margin-supported", IPP_TAG_INTEGER)) != nullptr) {
362         printerCaps.SetPrinterAttrNameAndValue("media-left-margin-supported",
363             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
364     }
365     if ((attrPtr = ippFindAttribute(response, "media-right-margin-supported", IPP_TAG_INTEGER)) != nullptr) {
366         printerCaps.SetPrinterAttrNameAndValue("media-right-margin-supported",
367             std::to_string(ippGetInteger(attrPtr, 0)).c_str());
368     }
369 }
370 
ParseOrientationAttributes(ipp_t * response,PrinterCapability & printerCaps)371 void ParseOrientationAttributes(ipp_t *response, PrinterCapability &printerCaps)
372 {
373     std::string keyword = "orientation-requested-default";
374     ipp_attribute_t *attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ENUM);
375     if (attrPtr != nullptr) {
376         int orientationEnum = ippGetInteger(attrPtr, 0);
377         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), std::to_string(orientationEnum).c_str());
378         PRINT_HILOGD("orientation-default found: %{public}d", orientationEnum);
379     }
380     keyword = "orientation-requested-supported";
381     attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ENUM);
382     if (attrPtr != nullptr) {
383         int num = ippGetCount(attrPtr);
384         if (num > 0) {
385             nlohmann::json supportedOrientationArray = nlohmann::json::array();
386             std::vector<uint32_t> supportedOrientations;
387             supportedOrientations.reserve(num);
388             for (int i = 0; i < ippGetCount(attrPtr); i++) {
389                 int orientationEnum = ippGetInteger(attrPtr, i);
390                 supportedOrientationArray.push_back(orientationEnum);
391                 supportedOrientations.emplace_back(orientationEnum);
392                 PRINT_HILOGD("orientation-supported found: %{public}d", orientationEnum);
393             }
394             printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), supportedOrientationArray.dump().c_str());
395             printerCaps.SetSupportedOrientation(supportedOrientations);
396         }
397     }
398 }
399 
ParseOtherAttributes(ipp_t * response,PrinterCapability & printerCaps)400 void ParseOtherAttributes(ipp_t *response, PrinterCapability &printerCaps)
401 {
402     std::string keyword = "media-source-supported";
403     std::string attrString = ConvertIppAttributesToJsonString(response, keyword);
404     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), attrString.c_str());
405     if (!attrString.empty()) {
406         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), attrString.c_str());
407     }
408 
409     keyword = "multiple-document-handling-supported";
410     attrString = ConvertIppAttributesToJsonString(response, keyword);
411     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), attrString.c_str());
412     if (!attrString.empty()) {
413         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), attrString.c_str());
414     }
415 }
416 
SetOptionAttribute(ipp_t * response,PrinterCapability & printerCaps)417 void SetOptionAttribute(ipp_t *response, PrinterCapability &printerCaps)
418 {
419     ipp_attribute_t *attrPtr;
420     nlohmann::json options;
421     if ((attrPtr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT)) != nullptr) {
422         options["make"] = ippGetString(attrPtr, 0, nullptr);
423     }
424     if ((attrPtr = ippFindAttribute(response, "printer-uuid", IPP_TAG_URI)) != nullptr) {
425         options["uuid"] = ippGetString(attrPtr, 0, nullptr);
426     }
427     if ((attrPtr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != nullptr) {
428         options["printerName"] = ippGetString(attrPtr, 0, nullptr);
429     }
430     std::string keyword = "media-type-supported";
431     std::string supportTypes;
432     std::vector<std::string> list;
433     attrPtr = ippFindAttribute(response, keyword.c_str(), IPP_TAG_ZERO);
434     if (attrPtr == nullptr) {
435         supportTypes = "";
436     } else {
437         nlohmann::json jsonArray = nlohmann::json::array();
438         for (int i = 0; i < ippGetCount(attrPtr); i++) {
439             const char *attrString = ippGetString(attrPtr, i, nullptr);
440             if (attrString == nullptr) {
441                 continue;
442             }
443             jsonArray.push_back(attrString);
444             list.emplace_back(attrString);
445         }
446         supportTypes = jsonArray.dump();
447     }
448     PRINT_HILOGD("%{public}s: %{public}s", keyword.c_str(), supportTypes.c_str());
449     if (!supportTypes.empty()) {
450         printerCaps.SetSupportedMediaType(list);
451         printerCaps.SetPrinterAttrNameAndValue(keyword.c_str(), supportTypes.c_str());
452     }
453 
454     nlohmann::json cupsOptionsJson = printerCaps.GetPrinterAttrGroupJson();
455     options["cupsOptions"] = cupsOptionsJson;
456 
457     std::string optionStr = options.dump();
458     PRINT_HILOGD("SetOption: %{public}s", optionStr.c_str());
459     printerCaps.SetOption(optionStr);
460 }
461 
ParsePrinterAttributes(ipp_t * response,PrinterCapability & printerCaps)462 void ParsePrinterAttributes(ipp_t *response, PrinterCapability &printerCaps)
463 {
464     SetCapabilityGroupAttribute(response, printerCaps);
465     ParseColorModeAttributes(response, printerCaps);
466     ParseDuplexModeAttributes(response, printerCaps);
467     ParsePageSizeAttributes(response, printerCaps);
468     ParseQualityAttributes(response, printerCaps);
469     ParseSupportedResolutionAttribute(response, printerCaps);
470     ParseDefaultResolutionAttribute(response, printerCaps);
471     ParseMediaColDefaultAttributes(response, printerCaps);
472     ParseMediaMarginAttributes(response, printerCaps);
473     ParseOrientationAttributes(response, printerCaps);
474     ParseCopiesAttributes(response, printerCaps);
475     ParseOtherAttributes(response, printerCaps);
476     SetOptionAttribute(response, printerCaps);
477 }
478 
ParsePrinterStatusAttributes(ipp_t * response,PrinterStatus & status)479 bool ParsePrinterStatusAttributes(ipp_t *response, PrinterStatus &status)
480 {
481     ipp_attribute_t *attrPtr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM);
482     if (attrPtr != nullptr) {
483         int enumValue = ippGetInteger(attrPtr, 0) - IPP_PSTATE_IDLE;
484         if (enumValue >= PRINTER_STATUS_IDLE && enumValue <= PRINTER_STATUS_UNAVAILABLE) {
485             status = static_cast<PrinterStatus>(enumValue);
486             return true;
487         }
488     }
489     return false;
490 }
491 }  // namespace OHOS::Print