1 /*
2  * Copyright (c) 2024 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 <securec.h>
17 #include "vendor_helper.h"
18 #include "print_service_converter.h"
19 #include "print_log.h"
20 
21 namespace {
22 const std::string VENDOR_MANAGER_PREFIX = "fwk.";
23 const std::string GLOBAL_ID_DELIMITER = ":";
24 const uint32_t ORIENTATION_OFFSET = 3;
25 const int NUMBER_BASE = 10;
26 const size_t MAX_STRING_COUNT = 1000;
27 }
28 
29 namespace OHOS::Print {
30 
CopyString(const std::string & source)31 char *CopyString(const std::string &source)
32 {
33     auto len = source.length();
34     char *dest = new (std::nothrow) char[len + 1];
35     if (dest == nullptr) {
36         PRINT_HILOGW("allocate failed");
37         return nullptr;
38     }
39     if (strcpy_s(dest, len + 1, source.c_str()) != 0) {
40         PRINT_HILOGW("CopyString strcpy_s failed");
41     }
42     dest[len] = '\0';
43     return dest;
44 }
45 
46 template <typename T1, typename T2>
ConvertArrayToList(const T1 * array,uint32_t count,std::vector<T2> & list,bool (* convertType)(const T1 &,T2 &))47 bool ConvertArrayToList(const T1 *array, uint32_t count, std::vector<T2> &list, bool (*convertType)(const T1 &, T2 &))
48 {
49     if (convertType == nullptr) {
50         PRINT_HILOGW("convertType is null");
51         return false;
52     }
53     if (count == 0) {
54         return true;
55     }
56     if (array == nullptr) {
57         PRINT_HILOGW("array is null");
58         return false;
59     }
60     for (uint32_t i = 0; i < count; ++i) {
61         T2 data;
62         if (convertType(array[i], data)) {
63             if (std::find(list.begin(), list.end(), data) != list.end()) {
64                 PRINT_HILOGW("ignore the same item");
65                 continue;
66             }
67             list.push_back(data);
68         }
69     }
70     return true;
71 }
72 
73 template <typename T>
ConvertArrayToJson(const T * array,uint32_t count,bool (* convertToJson)(const T &,nlohmann::json &))74 std::string ConvertArrayToJson(const T *array, uint32_t count, bool (*convertToJson)(const T &, nlohmann::json &))
75 {
76     if (array == nullptr || convertToJson == nullptr) {
77         PRINT_HILOGW("invalid params");
78         return "";
79     }
80     std::vector<T> list;
81     for (uint32_t i = 0; i < count; ++i) {
82         AddToUniqueList<T>(list, array[i]);
83     }
84     return ConvertListToJson<T>(list, convertToJson);
85 }
86 
ConvertJsonToStringList(const std::string & jsonString,std::vector<std::string> & list)87 bool ConvertJsonToStringList(const std::string &jsonString, std::vector<std::string> &list)
88 {
89     if (!nlohmann::json::accept(jsonString)) {
90         PRINT_HILOGW("invalid jsonString");
91         return false;
92     }
93     nlohmann::json jsonObject = nlohmann::json::parse(jsonString, nullptr, false);
94     if (jsonObject.is_discarded()) {
95         PRINT_HILOGW("jsonString discarded");
96         return false;
97     }
98     if (!jsonObject.is_array()) {
99         PRINT_HILOGW("jsonObject is not array");
100         return false;
101     }
102     for (auto &element : jsonObject.items()) {
103         nlohmann::json object = element.value();
104         if (object.is_string()) {
105             list.push_back(object.get<std::string>());
106         }
107     }
108     return true;
109 }
110 
GetStringValueFromJson(const nlohmann::json & jsonObject,const std::string & key)111 std::string GetStringValueFromJson(const nlohmann::json &jsonObject, const std::string &key)
112 {
113     if (!jsonObject.contains(key) || !jsonObject[key].is_string()) {
114         PRINT_HILOGW("can not find %{public}s", key.c_str());
115         return "";
116     }
117     return jsonObject[key].get<std::string>();
118 }
119 
ConvertStringToLong(const char * src,long & dst)120 bool ConvertStringToLong(const char *src, long &dst)
121 {
122     if (src == nullptr) {
123         return false;
124     }
125     errno = 0;
126     char *endPtr = nullptr;
127     dst = strtol(src, &endPtr, NUMBER_BASE);
128     if (errno == ERANGE || endPtr == src) {
129         PRINT_HILOGW("ConvertStringToLong fail: %{public}s", src);
130         return false;
131     }
132     return true;
133 }
134 
ConvertColorMode(const Print_ColorMode & code,uint32_t & dst)135 bool ConvertColorMode(const Print_ColorMode &code, uint32_t &dst)
136 {
137     dst = static_cast<uint32_t>(code);
138     if (dst > static_cast<uint32_t>(COLOR_MODE_AUTO)) {
139         return false;
140     }
141     return true;
142 }
ConvertColorModeToJson(const Print_ColorMode & code,nlohmann::json & jsonObject)143 bool ConvertColorModeToJson(const Print_ColorMode &code, nlohmann::json &jsonObject)
144 {
145     jsonObject["color"] = std::to_string(static_cast<int>(code));
146     return true;
147 }
148 
ConvertDuplexMode(const Print_DuplexMode & code,uint32_t & dst)149 bool ConvertDuplexMode(const Print_DuplexMode &code, uint32_t &dst)
150 {
151     dst = static_cast<uint32_t>(code);
152     if (dst > static_cast<uint32_t>(DUPLEX_MODE_TWO_SIDED_SHORT_EDGE)) {
153         return false;
154     }
155     return true;
156 }
ConvertDuplexModeToJson(const Print_DuplexMode & code,nlohmann::json & jsonObject)157 bool ConvertDuplexModeToJson(const Print_DuplexMode &code, nlohmann::json &jsonObject)
158 {
159     jsonObject["duplex"] = std::to_string(static_cast<int>(code));
160     return true;
161 }
162 
ConvertQuality(const Print_Quality & code,uint32_t & dst)163 bool ConvertQuality(const Print_Quality &code, uint32_t &dst)
164 {
165     dst = static_cast<uint32_t>(code);
166     if (dst < static_cast<uint32_t>(PRINT_QUALITY_DRAFT) || dst > static_cast<uint32_t>(PRINT_QUALITY_HIGH)) {
167         return false;
168     }
169     return true;
170 }
ConvertQualityToJson(const Print_Quality & code,nlohmann::json & jsonObject)171 bool ConvertQualityToJson(const Print_Quality &code, nlohmann::json &jsonObject)
172 {
173     jsonObject["quality"] = std::to_string(static_cast<int>(code));
174     return true;
175 }
176 
ConvertStringToPrinterState(const std::string & stateData,Print_PrinterState & state)177 bool ConvertStringToPrinterState(const std::string &stateData, Print_PrinterState &state)
178 {
179     long result = 0;
180     if (!nlohmann::json::accept(stateData)) {
181         PRINT_HILOGW("invalid stateData");
182         return false;
183     }
184     nlohmann::json jsonObject = nlohmann::json::parse(stateData, nullptr, false);
185     if (jsonObject.is_discarded()) {
186         PRINT_HILOGW("stateData discarded");
187         return false;
188     }
189     std::string stateValue = GetStringValueFromJson(jsonObject, "state");
190     if (!ConvertStringToLong(stateValue.c_str(), result)) {
191         return false;
192     }
193     std::string reasonValue = GetStringValueFromJson(jsonObject, "reason");
194     if (reasonValue == "shutdown") {
195         PRINT_HILOGD("printer shutdown");
196         state = PRINTER_UNAVAILABLE;
197         return true;
198     }
199     if (result < 0 || result > PRINTER_UNAVAILABLE + 1) {
200         PRINT_HILOGW("invalid state");
201         return false;
202     }
203     if (result == PRINTER_UNAVAILABLE + 1) {
204         state = PRINTER_UNAVAILABLE;
205     } else if (result == 1) {
206         state = PRINTER_BUSY;
207     } else {
208         state = PRINTER_IDLE;
209     }
210     return true;
211 }
212 
LogDiscoveryItem(const Print_DiscoveryItem * discoveryItem)213 void LogDiscoveryItem(const Print_DiscoveryItem *discoveryItem)
214 {
215     if (discoveryItem == nullptr) {
216         PRINT_HILOGW("discoveryItem is null");
217         return;
218     }
219     if (discoveryItem->printerId != nullptr) {
220         PRINT_HILOGD("printerId: %{public}s", discoveryItem->printerId);
221     } else {
222         PRINT_HILOGW("printerId is null");
223     }
224     if (discoveryItem->printerName != nullptr) {
225         PRINT_HILOGD("printerName: %{public}s", discoveryItem->printerName);
226     } else {
227         PRINT_HILOGW("printerName is null");
228     }
229     if (discoveryItem->description != nullptr) {
230         PRINT_HILOGD("description: %{public}s", discoveryItem->description);
231     }
232     if (discoveryItem->location != nullptr) {
233         PRINT_HILOGD("location: %{public}s", discoveryItem->location);
234     }
235     if (discoveryItem->makeAndModel != nullptr) {
236         PRINT_HILOGD("makeAndModel: %{public}s", discoveryItem->makeAndModel);
237     } else {
238         PRINT_HILOGW("makeAndModel is null");
239     }
240     if (discoveryItem->printerUri != nullptr) {
241         PRINT_HILOGD("printerUri: %{public}s", discoveryItem->printerUri);
242     } else {
243         PRINT_HILOGW("printerUri is null");
244     }
245     if (discoveryItem->printerUuid != nullptr) {
246         PRINT_HILOGD("printerUuid: %{public}s", discoveryItem->printerUuid);
247     }
248 }
249 
LogPageCapability(const Print_PrinterCapability * capability)250 void LogPageCapability(const Print_PrinterCapability *capability)
251 {
252     if (capability == nullptr) {
253         PRINT_HILOGW("capability is null");
254         return;
255     }
256     if (capability->supportedPageSizes != nullptr && capability->supportedPageSizesCount > 0) {
257         for (uint32_t i = 0; i < capability->supportedPageSizesCount; ++i) {
258             if (capability->supportedPageSizes[i].id != nullptr) {
259                 PRINT_HILOGD("page id = %{public}s", capability->supportedPageSizes[i].id);
260             }
261             if (capability->supportedPageSizes[i].name != nullptr) {
262                 PRINT_HILOGD("page name = %{public}s", capability->supportedPageSizes[i].name);
263             }
264             PRINT_HILOGD("page size = %{public}u x %{public}u", capability->supportedPageSizes[i].width,
265                          capability->supportedPageSizes[i].height);
266         }
267     }
268     if (capability->supportedMediaTypes != nullptr) {
269         PRINT_HILOGD("media types = %{public}s", capability->supportedMediaTypes);
270     }
271     if (capability->supportedPaperSources != nullptr) {
272         PRINT_HILOGD("Paper Sources = %{public}s", capability->supportedPaperSources);
273     }
274 }
275 
LogOtherCapability(const Print_PrinterCapability * capability)276 void LogOtherCapability(const Print_PrinterCapability *capability)
277 {
278     if (capability == nullptr) {
279         PRINT_HILOGW("capability is null");
280         return;
281     }
282     if (capability->supportedColorModes != nullptr && capability->supportedColorModesCount > 0) {
283         for (uint32_t i = 0; i < capability->supportedColorModesCount; ++i) {
284             PRINT_HILOGD("color mode = %{public}u", static_cast<uint32_t>(capability->supportedColorModes[i]));
285         }
286     }
287     if (capability->supportedDuplexModes != nullptr && capability->supportedDuplexModesCount > 0) {
288         for (uint32_t i = 0; i < capability->supportedDuplexModesCount; ++i) {
289             PRINT_HILOGD("duplex mode = %{public}u", static_cast<uint32_t>(capability->supportedDuplexModes[i]));
290         }
291     }
292     if (capability->supportedQualities != nullptr && capability->supportedQualitiesCount > 0) {
293         for (uint32_t i = 0; i < capability->supportedQualitiesCount; ++i) {
294             PRINT_HILOGD("quality mode = %{public}u", static_cast<uint32_t>(capability->supportedQualities[i]));
295         }
296     }
297     PRINT_HILOGD("copy count = %{public}u", capability->supportedCopies);
298     if (capability->supportedResolutions != nullptr && capability->supportedResolutionsCount > 0) {
299         for (uint32_t i = 0; i < capability->supportedResolutionsCount; ++i) {
300             PRINT_HILOGD("dpi = %{public}u x %{public}u", capability->supportedResolutions[i].horizontalDpi,
301                          capability->supportedResolutions[i].verticalDpi);
302         }
303     }
304     if (capability->supportedOrientations != nullptr && capability->supportedOrientationsCount > 0) {
305         for (uint32_t i = 0; i < capability->supportedOrientationsCount; ++i) {
306             PRINT_HILOGD("Orientation = %{public}u", static_cast<uint32_t>(capability->supportedOrientations[i]));
307         }
308     }
309     if (capability->advancedCapability != nullptr) {
310         PRINT_HILOGD("advancedCapability = %{public}s", capability->advancedCapability);
311     }
312 }
313 
LogDefaultValue(const Print_DefaultValue * defaultValue)314 void LogDefaultValue(const Print_DefaultValue *defaultValue)
315 {
316     if (defaultValue == nullptr) {
317         PRINT_HILOGW("defaultValue is null");
318         return;
319     }
320     PRINT_HILOGD("default color mode = %{public}u", static_cast<uint32_t>(defaultValue->defaultColorMode));
321     PRINT_HILOGD("default duplex mode = %{public}u", static_cast<uint32_t>(defaultValue->defaultDuplexMode));
322     if (defaultValue->defaultMediaType != nullptr) {
323         PRINT_HILOGD("defaultMediaType = %{public}s", defaultValue->defaultMediaType);
324     }
325     if (defaultValue->defaultPageSizeId != nullptr) {
326         PRINT_HILOGD("defaultPageSizeId = %{public}s", defaultValue->defaultPageSizeId);
327     }
328     PRINT_HILOGD("defaultMargin = [%{public}u, %{public}u, %{public}u, %{public}u]",
329                  defaultValue->defaultMargin.leftMargin, defaultValue->defaultMargin.topMargin,
330                  defaultValue->defaultMargin.rightMargin, defaultValue->defaultMargin.bottomMargin);
331     if (defaultValue->defaultPaperSource != nullptr) {
332         PRINT_HILOGD("defaultPaperSource = %{public}s", defaultValue->defaultPaperSource);
333     }
334     PRINT_HILOGD("defaultPrintQuality = %{public}u", static_cast<uint32_t>(defaultValue->defaultPrintQuality));
335     PRINT_HILOGD("defaultCopies = %{public}u", defaultValue->defaultCopies);
336     PRINT_HILOGD("defaultResolution = %{public}u x %{public}u", defaultValue->defaultResolution.horizontalDpi,
337                  defaultValue->defaultResolution.verticalDpi);
338     PRINT_HILOGD("defaultOrientation = %{public}u", static_cast<uint32_t>(defaultValue->defaultOrientation));
339     if (defaultValue->otherDefaultValues != nullptr) {
340         PRINT_HILOGD("otherDefaultValues = %{public}s", defaultValue->otherDefaultValues);
341     }
342 }
343 
LogProperties(const Print_PropertyList * propertyList)344 void LogProperties(const Print_PropertyList *propertyList)
345 {
346     if (propertyList == nullptr) {
347         PRINT_HILOGW("propertyList is null");
348         return;
349     }
350     if (propertyList->count == 0 || propertyList->list == nullptr) {
351         PRINT_HILOGW("propertyList empty");
352         return;
353     }
354     for (uint32_t i = 0; i < propertyList->count; ++i) {
355         if (propertyList->list[i].key == nullptr) {
356             PRINT_HILOGW("propertyList item empty: %{public}u", i);
357             continue;
358         }
359         PRINT_HILOGD("LogProperties key: %{public}s", propertyList->list[i].key);
360         if (propertyList->list[i].value == nullptr) {
361             PRINT_HILOGW("propertyList value empty: %{public}u", i);
362             continue;
363         }
364         PRINT_HILOGD("LogProperties value: %{public}s", propertyList->list[i].value);
365     }
366 }
367 
FindPropertyFromPropertyList(const Print_PropertyList * propertyList,const std::string & keyName)368 std::string FindPropertyFromPropertyList(const Print_PropertyList *propertyList, const std::string &keyName)
369 {
370     if (propertyList == nullptr) {
371         PRINT_HILOGW("propertyList is null");
372         return "";
373     }
374     if (propertyList->count == 0 || propertyList->list == nullptr) {
375         PRINT_HILOGW("propertyList empty");
376         return "";
377     }
378     for (uint32_t i = 0; i < propertyList->count; ++i) {
379         if (propertyList->list[i].key == nullptr) {
380             PRINT_HILOGW("propertyList key empty: %{public}u", i);
381             continue;
382         }
383         PRINT_HILOGD("FindPropertyFromPropertyList key: %{public}s", propertyList->list[i].key);
384         if (strcmp(keyName.c_str(), propertyList->list[i].key) != 0) {
385             continue;
386         }
387         if (propertyList->list[i].value == nullptr) {
388             PRINT_HILOGW("propertyList value empty, key: %{public}s", keyName.c_str());
389             break;
390         }
391         PRINT_HILOGD("FindPropertyFromPropertyList value: %{public}s", propertyList->list[i].value);
392         return std::string(propertyList->list[i].value);
393     }
394     return "";
395 }
UpdatePrinterInfoWithDiscovery(PrinterInfo & info,const Print_DiscoveryItem * discoveryItem)396 bool UpdatePrinterInfoWithDiscovery(PrinterInfo &info, const Print_DiscoveryItem *discoveryItem)
397 {
398     if (discoveryItem == nullptr) {
399         PRINT_HILOGW("discoveryItem is null");
400         return false;
401     }
402     if (discoveryItem->printerId == nullptr || discoveryItem->printerName == nullptr) {
403         PRINT_HILOGW("invalid discoveryItem");
404         return false;
405     }
406     info.SetPrinterId(std::string(discoveryItem->printerId));
407     std::string name(discoveryItem->printerName);
408     info.SetPrinterName(name);
409     if (discoveryItem->description != nullptr) {
410         info.SetDescription(std::string(discoveryItem->description));
411     }
412     if (discoveryItem->printerUri != nullptr) {
413         info.SetUri(std::string(discoveryItem->printerUri));
414     }
415     if (discoveryItem->makeAndModel != nullptr) {
416         info.SetPrinterMake(std::string(discoveryItem->makeAndModel));
417     }
418     if (discoveryItem->printerUri != nullptr && discoveryItem->makeAndModel != nullptr) {
419         PRINT_HILOGD("printerUri: %{public}s", discoveryItem->printerUri);
420         nlohmann::json option;
421         option["printerName"] = name;
422         option["printerUri"] = std::string(discoveryItem->printerUri);
423         option["make"] = std::string(discoveryItem->makeAndModel);
424         if (discoveryItem->printerUuid != nullptr) {
425             option["printer-uuid"] = std::string(discoveryItem->printerUuid);
426         }
427         if (discoveryItem->detailInfo != nullptr && nlohmann::json::accept(std::string(discoveryItem->detailInfo))) {
428             nlohmann::json detailInfo = nlohmann::json::parse(std::string(discoveryItem->detailInfo));
429             if (!detailInfo.is_null() && detailInfo.contains("bsunidriver_support") &&
430                 detailInfo["bsunidriver_support"].is_string()) {
431                 option["bsunidriverSupport"] = detailInfo["bsunidriver_support"].get<std::string>();
432             }
433         }
434         info.SetOption(option.dump());
435     }
436     return true;
437 }
438 
AddUniquePageSize(std::vector<PrintPageSize> & pageSizeList,const PrintPageSize & printPageSize)439 void AddUniquePageSize(std::vector<PrintPageSize> &pageSizeList, const PrintPageSize &printPageSize)
440 {
441     for (auto const &item : pageSizeList) {
442         if (item.GetId() == printPageSize.GetId()) {
443             return;
444         }
445     }
446     pageSizeList.push_back(printPageSize);
447 }
448 
UpdateDefaultPageSizeId(PrinterCapability & printerCap,const std::string & defaultPageId,const std::string & pageId,const Print_PageSize & page)449 bool UpdateDefaultPageSizeId(PrinterCapability &printerCap, const std::string &defaultPageId, const std::string &pageId,
450                              const Print_PageSize &page)
451 {
452     if (page.id != nullptr && defaultPageId == std::string(page.id)) {
453         printerCap.SetPrinterAttrNameAndValue("defaultPageSizeId", pageId.c_str());
454         return true;
455     }
456     return false;
457 }
458 
UpdatePageSizeCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)459 bool UpdatePageSizeCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability,
460                               const Print_DefaultValue *defaultValue)
461 {
462     if (capability == nullptr || capability->supportedPageSizes == nullptr) {
463         PRINT_HILOGW("supportedPageSizes is null");
464         return false;
465     }
466     std::string defaultPageId;
467     if (defaultValue != nullptr && defaultValue->defaultPageSizeId != nullptr) {
468         defaultPageId = defaultValue->defaultPageSizeId;
469     }
470     std::vector<PrintPageSize> pageSizeList;
471     for (uint32_t i = 0; i < capability->supportedPageSizesCount; ++i) {
472         PrintPageSize printPageSize;
473         if (capability->supportedPageSizes[i].name != nullptr) {
474             std::string pageSizeName(capability->supportedPageSizes[i].name);
475             PAGE_SIZE_ID id = PrintPageSize::MatchPageSize(pageSizeName);
476             if (!id.empty() && PrintPageSize::FindPageSizeById(id, printPageSize)) {
477                 AddUniquePageSize(pageSizeList, printPageSize);
478                 UpdateDefaultPageSizeId(printerCap, defaultPageId, id, capability->supportedPageSizes[i]);
479                 PRINT_HILOGD("page size matched = %{public}s", id.c_str());
480                 continue;
481             }
482         }
483         if (capability->supportedPageSizes[i].id != nullptr) {
484             PAGE_SIZE_ID id = std::string(capability->supportedPageSizes[i].id);
485             if (!id.empty() && PrintPageSize::FindPageSizeById(id, printPageSize)) {
486                 AddUniquePageSize(pageSizeList, printPageSize);
487                 UpdateDefaultPageSizeId(printerCap, defaultPageId, id, capability->supportedPageSizes[i]);
488                 PRINT_HILOGD("page size matched = %{public}s", id.c_str());
489                 continue;
490             }
491         }
492         PRINT_HILOGD("page size = %{public}u x %{public}u", capability->supportedPageSizes[i].width,
493                      capability->supportedPageSizes[i].height);
494     }
495     printerCap.SetSupportedPageSize(pageSizeList);
496     return true;
497 }
498 
UpdateQualityCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability)499 bool UpdateQualityCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability)
500 {
501     if (capability == nullptr || capability->supportedQualities == nullptr) {
502         PRINT_HILOGW("supportedQualities is null");
503         return false;
504     }
505     std::vector<uint32_t> supportedQualityList;
506     if (ConvertArrayToList<Print_Quality, uint32_t>(capability->supportedQualities,
507         capability->supportedQualitiesCount, supportedQualityList, ConvertQuality)) {
508         printerCap.SetSupportedQuality(supportedQualityList);
509     }
510     std::string supportedQualities = ConvertArrayToJson<Print_Quality>(
511         capability->supportedQualities, capability->supportedQualitiesCount, ConvertQualityToJson);
512     PRINT_HILOGD("quality: %{public}s", supportedQualities.c_str());
513     if (!supportedQualities.empty()) {
514         printerCap.SetPrinterAttrNameAndValue("print-quality-supported", supportedQualities.c_str());
515     }
516     return true;
517 }
518 
UpdateColorCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability)519 bool UpdateColorCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability)
520 {
521     if (capability == nullptr || capability->supportedColorModes == nullptr) {
522         PRINT_HILOGW("supportedColorModes is null");
523         return false;
524     }
525     std::vector<uint32_t> supportedColorModes;
526     if (ConvertArrayToList<Print_ColorMode, uint32_t>(capability->supportedColorModes,
527         capability->supportedColorModesCount, supportedColorModes, ConvertColorMode)) {
528         printerCap.SetSupportedColorMode(supportedColorModes);
529     }
530     std::string colorModeJson = ConvertArrayToJson<Print_ColorMode>(
531         capability->supportedColorModes, capability->supportedColorModesCount, ConvertColorModeToJson);
532     if (!colorModeJson.empty()) {
533         printerCap.SetPrinterAttrNameAndValue("print-color-mode-supported", colorModeJson.c_str());
534     }
535     for (uint32_t i = 0; i < capability->supportedColorModesCount; ++i) {
536         if (capability->supportedColorModes[i] == Print_ColorMode::COLOR_MODE_COLOR) {
537             printerCap.SetColorMode(ColorModeCode::COLOR_MODE_COLOR);
538             break;
539         }
540     }
541     return true;
542 }
543 
UpdateDuplexCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability)544 bool UpdateDuplexCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability)
545 {
546     if (capability == nullptr || capability->supportedDuplexModes == nullptr) {
547         PRINT_HILOGW("supportedDuplexModes is null");
548         return false;
549     }
550     std::vector<uint32_t> supportedDuplexModes;
551     if (ConvertArrayToList<Print_DuplexMode, uint32_t>(capability->supportedDuplexModes,
552         capability->supportedDuplexModesCount, supportedDuplexModes, ConvertDuplexMode)) {
553         printerCap.SetSupportedDuplexMode(supportedDuplexModes);
554     }
555     std::string duplexModeJson = ConvertArrayToJson<Print_DuplexMode>(
556         capability->supportedDuplexModes, capability->supportedDuplexModesCount, ConvertDuplexModeToJson);
557     if (!duplexModeJson.empty()) {
558         printerCap.SetPrinterAttrNameAndValue("sides-supported", duplexModeJson.c_str());
559     }
560     if (capability->supportedDuplexModesCount > 1) {
561         printerCap.SetDuplexMode(static_cast<uint32_t>(Print_DuplexMode::DUPLEX_MODE_TWO_SIDED_LONG_EDGE));
562     }
563     return true;
564 }
UpdateResolutionCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability)565 bool UpdateResolutionCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability)
566 {
567     if (capability == nullptr || capability->supportedResolutions == nullptr) {
568         PRINT_HILOGW("supportedResolutions is null");
569         return false;
570     }
571     std::vector<PrintResolution> resolutionList;
572     nlohmann::json resolutionArray = nlohmann::json::array();
573     for (uint32_t i = 0; i < capability->supportedResolutionsCount; ++i) {
574         PrintResolution printResolution;
575         uint32_t xRes = capability->supportedResolutions[i].horizontalDpi;
576         uint32_t yRes = capability->supportedResolutions[i].verticalDpi;
577         printResolution.SetHorizontalDpi(xRes);
578         printResolution.SetVerticalDpi(yRes);
579         PRINT_HILOGD("resolution = %{public}u x %{public}u", xRes, yRes);
580         resolutionList.push_back(printResolution);
581         nlohmann::json object;
582         object["horizontalDpi"] = xRes;
583         object["verticalDpi"] = yRes;
584         resolutionArray.push_back(object);
585     }
586     printerCap.SetResolution(resolutionList);
587     printerCap.SetPrinterAttrNameAndValue("printer-resolution-supported", resolutionArray.dump().c_str());
588     return true;
589 }
590 
UpdateResolutionDefaultValue(PrinterCapability & printerCap,const Print_DefaultValue * defaultValue)591 bool UpdateResolutionDefaultValue(PrinterCapability &printerCap, const Print_DefaultValue *defaultValue)
592 {
593     if (defaultValue == nullptr) {
594         PRINT_HILOGW("defaultValue is null");
595         return false;
596     }
597     nlohmann::json object;
598     object["horizontalDpi"] = defaultValue->defaultResolution.horizontalDpi;
599     object["verticalDpi"] = defaultValue->defaultResolution.verticalDpi;
600     printerCap.SetPrinterAttrNameAndValue("printer-resolution-default", object.dump().c_str());
601     return true;
602 }
603 
UpdateCopiesCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)604 bool UpdateCopiesCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability,
605                             const Print_DefaultValue *defaultValue)
606 {
607     if (capability == nullptr || defaultValue == nullptr) {
608         PRINT_HILOGW("capability or defaultValue is null");
609         return false;
610     }
611     printerCap.SetPrinterAttrNameAndValue("copies-supported", std::to_string(capability->supportedCopies).c_str());
612     printerCap.SetPrinterAttrNameAndValue("copies-default", std::to_string(defaultValue->defaultCopies).c_str());
613     return true;
614 }
615 
UpdateOrientationCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)616 bool UpdateOrientationCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability,
617                                  const Print_DefaultValue *defaultValue)
618 {
619     if (capability == nullptr || defaultValue == nullptr) {
620         PRINT_HILOGW("capability or defaultValue is null");
621         return false;
622     }
623     printerCap.SetPrinterAttrNameAndValue("orientation-requested-default",
624                                           std::to_string(defaultValue->defaultOrientation).c_str());
625     if (capability->supportedOrientations != nullptr) {
626         nlohmann::json supportedOrientationArray = nlohmann::json::array();
627         std::vector<uint32_t> supportedOrientations;
628         for (uint32_t i = 0; i < capability->supportedOrientationsCount; ++i) {
629             int orientationEnum = static_cast<int>(capability->supportedOrientations[i]) + ORIENTATION_OFFSET;
630             supportedOrientationArray.push_back(orientationEnum);
631             supportedOrientations.push_back(static_cast<uint32_t>(orientationEnum));
632         }
633         printerCap.SetSupportedOrientation(supportedOrientations);
634         printerCap.SetPrinterAttrNameAndValue("orientation-requested-supported",
635                                               supportedOrientationArray.dump().c_str());
636     }
637     return true;
638 }
639 
UpdateMediaCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)640 bool UpdateMediaCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability,
641                            const Print_DefaultValue *defaultValue)
642 {
643     if (capability == nullptr || defaultValue == nullptr) {
644         PRINT_HILOGW("capability or defaultValue is null");
645         return false;
646     }
647     if (capability->supportedMediaTypes != nullptr) {
648         printerCap.SetPrinterAttrNameAndValue("media-type-supported", capability->supportedMediaTypes);
649         std::string mdiaTypeJson(capability->supportedMediaTypes);
650         std::vector<std::string> mediaTypeList;
651         if (ConvertJsonToStringList(mdiaTypeJson, mediaTypeList)) {
652             printerCap.SetSupportedMediaType(mediaTypeList);
653         } else {
654             PRINT_HILOGW("invalid media types");
655         }
656     }
657     if (defaultValue->defaultMediaType != nullptr) {
658         printerCap.SetPrinterAttrNameAndValue("media-type-default", defaultValue->defaultMediaType);
659     }
660     if (capability->supportedPaperSources != nullptr) {
661         printerCap.SetPrinterAttrNameAndValue("media-source-supported", capability->supportedPaperSources);
662     }
663     if (defaultValue->defaultPaperSource != nullptr) {
664         printerCap.SetPrinterAttrNameAndValue("media-source-default", defaultValue->defaultPaperSource);
665     }
666     return true;
667 }
UpdateMarginCapability(PrinterCapability & printerCap,const Print_DefaultValue * defaultValue)668 bool UpdateMarginCapability(PrinterCapability &printerCap, const Print_DefaultValue *defaultValue)
669 {
670     if (defaultValue == nullptr) {
671         PRINT_HILOGW("defaultValue is null");
672         return false;
673     }
674     PrintMargin printMargin;
675     printMargin.SetLeft(defaultValue->defaultMargin.leftMargin);
676     printMargin.SetTop(defaultValue->defaultMargin.topMargin);
677     printMargin.SetRight(defaultValue->defaultMargin.rightMargin);
678     printMargin.SetBottom(defaultValue->defaultMargin.bottomMargin);
679     PRINT_HILOGD("margin left = %{public}u, top =  %{public}u, right = %{public}u, bottom =  %{public}u",
680                  defaultValue->defaultMargin.leftMargin, defaultValue->defaultMargin.topMargin,
681                  defaultValue->defaultMargin.rightMargin, defaultValue->defaultMargin.bottomMargin);
682     printerCap.SetMinMargin(printMargin);
683     return true;
684 }
UpdatePrinterCapability(PrinterCapability & printerCap,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)685 bool UpdatePrinterCapability(PrinterCapability &printerCap, const Print_PrinterCapability *capability,
686                              const Print_DefaultValue *defaultValue)
687 {
688     if (capability == nullptr || defaultValue == nullptr) {
689         PRINT_HILOGW("capability or defaultValue is null");
690         return false;
691     }
692     if (!UpdatePageSizeCapability(printerCap, capability, defaultValue)) {
693         return false;
694     }
695     UpdateColorCapability(printerCap, capability);
696     uint32_t defaultColorMode = static_cast<uint32_t>(defaultValue->defaultColorMode);
697     printerCap.SetPrinterAttrNameAndValue("defaultColorMode", std::to_string(defaultColorMode).c_str());
698     UpdateDuplexCapability(printerCap, capability);
699     uint32_t defaultDuplexMode = static_cast<uint32_t>(defaultValue->defaultDuplexMode);
700     printerCap.SetPrinterAttrNameAndValue("sides-default", std::to_string(defaultDuplexMode).c_str());
701     UpdateQualityCapability(printerCap, capability);
702     UpdateResolutionCapability(printerCap, capability);
703     UpdateResolutionDefaultValue(printerCap, defaultValue);
704     UpdateCopiesCapability(printerCap, capability, defaultValue);
705     UpdateOrientationCapability(printerCap, capability, defaultValue);
706     UpdateMediaCapability(printerCap, capability, defaultValue);
707     UpdateMarginCapability(printerCap, defaultValue);
708     return true;
709 }
710 
UpdatePrinterInfoWithCapability(PrinterInfo & info,const Print_DiscoveryItem * discoveryItem,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)711 bool UpdatePrinterInfoWithCapability(PrinterInfo &info, const Print_DiscoveryItem *discoveryItem,
712                                      const Print_PrinterCapability *capability, const Print_DefaultValue *defaultValue)
713 {
714     PrinterCapability printerCap;
715     if (!UpdatePrinterCapability(printerCap, capability, defaultValue)) {
716         PRINT_HILOGW("update capability fail");
717         return false;
718     }
719     nlohmann::json options;
720     if (discoveryItem != nullptr) {
721         if (discoveryItem->makeAndModel != nullptr) {
722             options["make"] = std::string(discoveryItem->makeAndModel);
723         }
724         if (discoveryItem->printerName != nullptr) {
725             options["printerName"] = info.GetPrinterName();
726         }
727         if (discoveryItem->printerUuid != nullptr) {
728             options["printer-uuid"] = std::string(discoveryItem->printerUuid);
729         }
730     }
731     nlohmann::json cupsOptionsJson = printerCap.GetPrinterAttrGroupJson();
732     options["cupsOptions"] = cupsOptionsJson;
733     std::string optionStr = options.dump();
734     PRINT_HILOGD("SetOption: %{public}s", optionStr.c_str());
735     printerCap.SetOption(optionStr);
736     info.SetCapability(printerCap);
737     info.Dump();
738     return true;
739 }
740 
ConvertVendorCapabilityToPrinterInfo(const Print_DiscoveryItem * printer,const Print_PrinterCapability * capability,const Print_DefaultValue * defaultValue)741 std::shared_ptr<PrinterInfo> ConvertVendorCapabilityToPrinterInfo(const Print_DiscoveryItem *printer,
742                                                                   const Print_PrinterCapability *capability,
743                                                                   const Print_DefaultValue *defaultValue)
744 {
745     if (printer == nullptr || printer->printerId == nullptr) {
746         PRINT_HILOGW("printer null");
747         return nullptr;
748     }
749     std::shared_ptr<PrinterInfo> info = std::make_shared<PrinterInfo>();
750     if (info == nullptr) {
751         return nullptr;
752     }
753     if (!UpdatePrinterInfoWithDiscovery(*info, printer)) {
754         PRINT_HILOGW("update printer info fail");
755         return nullptr;
756     }
757     UpdatePrinterInfoWithCapability(*info, printer, capability, defaultValue);
758     return info;
759 }
760 
ConvertStringVectorToStringList(const std::vector<std::string> & stringVector,Print_StringList & stringList)761 bool ConvertStringVectorToStringList(const std::vector<std::string> &stringVector, Print_StringList &stringList)
762 {
763     size_t count = stringVector.size();
764     if (count == 0 || count > MAX_STRING_COUNT) {
765         return false;
766     }
767     stringList.count = 0;
768     stringList.list = new (std::nothrow) char *[count];
769     if (stringList.list == nullptr) {
770         PRINT_HILOGW("stringList list allocate fail");
771         return false;
772     }
773     if (memset_s(stringList.list, count * sizeof(char *), 0, count * sizeof(char *)) != 0) {
774         PRINT_HILOGW("memset_s fail");
775         delete[] stringList.list;
776         stringList.list = nullptr;
777         return false;
778     }
779     for (auto const &key : stringVector) {
780         stringList.list[stringList.count] = CopyString(key);
781         stringList.count++;
782     }
783     return true;
784 }
785 
ReleaseStringList(Print_StringList & stringList)786 void ReleaseStringList(Print_StringList &stringList)
787 {
788     if (stringList.list != nullptr) {
789         for (uint32_t i = 0; i < stringList.count; i++) {
790             if (stringList.list[i] != nullptr) {
791                 delete[] stringList.list[i];
792                 stringList.list[i] = nullptr;
793             }
794         }
795         delete[] stringList.list;
796         stringList.list = nullptr;
797     }
798     stringList.count = 0;
799 }
800 }
801