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 <vector>
17 #include <nlohmann/json.hpp>
18 
19 #include "print_helper.h"
20 #include "print_constant.h"
21 #include "print_log.h"
22 #include "print_util.h"
23 #include "ability_manager_client.h"
24 #include "print_converter.h"
25 #include "print_manager_client.h"
26 #include "print_util.h"
27 
28 using json = nlohmann::json;
29 
30 namespace OHOS::Print {
31 
32 const std::string DUPLEX_STRING = "duplex";
33 const std::string ORIENTATION_STRING = "orientation";
34 const std::string PAGESIZEID_STRING = "pagesizeId";
35 const std::string QUALITY_STRING = "quality";
36 const std::string DEFAULT_QUALITY_PREFERENCE = "4";
37 const int NUMBER_BASE = 10;
38 
CopyString(const std::string & source)39 char *CopyString(const std::string &source)
40 {
41     auto len = source.length();
42     char *dest = new (std::nothrow) char[len + 1];
43     if (dest == nullptr) {
44         PRINT_HILOGW("allocate failed");
45         return nullptr;
46     }
47     if (strcpy_s(dest, len + 1, source.c_str()) != 0) {
48         PRINT_HILOGW("CopyString strcpy_s failed");
49     }
50     dest[len] = '\0';
51     return dest;
52 }
53 
AddJsonFieldStringToJsonObject(const nlohmann::json & cupsOpt,const std::string & keyword,nlohmann::json & advancedCapJson)54 void AddJsonFieldStringToJsonObject(const nlohmann::json &cupsOpt, const std::string &keyword,
55     nlohmann::json &advancedCapJson)
56 {
57     PRINT_HILOGD("AddJsonFieldStringToJsonObject %{public}s", keyword.c_str());
58     if (!cupsOpt.contains(keyword)) {
59         PRINT_HILOGW("missing keyword");
60         return;
61     }
62     if (!cupsOpt[keyword].is_string()) {
63         PRINT_HILOGW("not string type");
64         return;
65     }
66     std::string optionString = cupsOpt[keyword].get<std::string>();
67     PRINT_HILOGD("AddJsonFieldStringToJsonObject %{public}s", optionString.c_str());
68     advancedCapJson[keyword] = optionString;
69 }
70 
ParseJsonFieldAsArrayOpt(const nlohmann::json & cupsOpt,const std::string & key,Print_PrinterInfo & nativePrinterInfo,void (* arrayOpteration)(const nlohmann::json &,Print_PrinterInfo &))71 void ParseJsonFieldAsArrayOpt(const nlohmann::json &cupsOpt, const std::string &key,
72     Print_PrinterInfo &nativePrinterInfo, void (*arrayOpteration)(const nlohmann::json &, Print_PrinterInfo &))
73 {
74     PRINT_HILOGD("ParseJsonFieldAsArrayOpt: %{public}s", key.c_str());
75     if (arrayOpteration == nullptr) {
76         PRINT_HILOGW("arrayOpteration is null");
77         return;
78     }
79     if (!cupsOpt.contains(key)) {
80         PRINT_HILOGW("key missing");
81         return;
82     }
83     if (!cupsOpt[key].is_string()) {
84         PRINT_HILOGW("not string");
85         return;
86     }
87     std::string arrayJson = cupsOpt[key].get<std::string>();
88     if (!nlohmann::json::accept(arrayJson)) {
89         PRINT_HILOGW("accept fail");
90         return;
91     }
92     nlohmann::json arrayOpt = nlohmann::json::parse(arrayJson);
93     if (!arrayOpt.is_array()) {
94         PRINT_HILOGW("not array");
95         return;
96     }
97     arrayOpteration(arrayOpt, nativePrinterInfo);
98 }
99 
ParseJsonFieldAsInt(const nlohmann::json & cupsOpt,const std::string & key,int & value)100 bool ParseJsonFieldAsInt(const nlohmann::json &cupsOpt, const std::string &key, int &value)
101 {
102     if (!cupsOpt.contains(key)) {
103         PRINT_HILOGW("key missing");
104         return false;
105     }
106     if (cupsOpt[key].is_number()) {
107         value = cupsOpt[key];
108         return true;
109     }
110     if (!cupsOpt[key].is_string()) {
111         PRINT_HILOGW("incorrect type");
112         return false;
113     }
114     std::string jsonString = cupsOpt[key].get<std::string>();
115     if (!jsonString.empty() && ConvertStringToInt(jsonString.c_str(), value)) {
116         return true;
117     }
118     return false;
119 }
120 
ConvertJsonArrayToIntList(const nlohmann::json & jsonArray,const std::string & key,std::vector<uint32_t> & list)121 void ConvertJsonArrayToIntList(const nlohmann::json &jsonArray, const std::string &key, std::vector<uint32_t> &list)
122 {
123     PRINT_HILOGD("ConvertJsonArrayToIntList %{public}s, %{public}zu", key.c_str(), jsonArray.size());
124     for (auto &item : jsonArray) {
125         int value = 0;
126         if (!ParseJsonFieldAsInt(item, key, value)) {
127             continue;
128         }
129         list.push_back(static_cast<uint32_t>(value));
130     }
131 }
132 
ReleaseCapabilityPageSizes(Print_PrinterCapability & capability)133 void ReleaseCapabilityPageSizes(Print_PrinterCapability &capability)
134 {
135     if (capability.supportedPageSizes != nullptr) {
136         for (uint32_t i = 0; i < capability.supportedPageSizesCount; i++) {
137             SAFE_DELETE_ARRAY(capability.supportedPageSizes[i].id);
138             SAFE_DELETE_ARRAY(capability.supportedPageSizes[i].name);
139         }
140         SAFE_DELETE_ARRAY(capability.supportedPageSizes);
141     }
142     capability.supportedPageSizesCount = 0;
143 }
144 
ReleaseCapability(Print_PrinterCapability & capability)145 void ReleaseCapability(Print_PrinterCapability &capability)
146 {
147     ReleaseCapabilityPageSizes(capability);
148     SAFE_DELETE_ARRAY(capability.supportedColorModes);
149     capability.supportedColorModesCount = 0;
150     SAFE_DELETE_ARRAY(capability.supportedDuplexModes);
151     capability.supportedDuplexModesCount = 0;
152     SAFE_DELETE_ARRAY(capability.supportedMediaTypes);
153     SAFE_DELETE_ARRAY(capability.supportedQualities);
154     capability.supportedQualitiesCount = 0;
155     SAFE_DELETE_ARRAY(capability.supportedPaperSources);
156     SAFE_DELETE_ARRAY(capability.supportedResolutions);
157     capability.supportedResolutionsCount = 0;
158     SAFE_DELETE_ARRAY(capability.supportedOrientations);
159     capability.supportedOrientationsCount = 0;
160     SAFE_DELETE_ARRAY(capability.advancedCapability);
161 }
162 
ReleaseDefaultValue(Print_DefaultValue & defaultValue)163 void ReleaseDefaultValue(Print_DefaultValue &defaultValue)
164 {
165     SAFE_DELETE_ARRAY(defaultValue.defaultPageSizeId);
166     SAFE_DELETE_ARRAY(defaultValue.defaultMediaType);
167     SAFE_DELETE_ARRAY(defaultValue.defaultPaperSource);
168     SAFE_DELETE_ARRAY(defaultValue.otherDefaultValues);
169 }
170 
ReleasePrinterInfo(Print_PrinterInfo & printerInfo)171 void ReleasePrinterInfo(Print_PrinterInfo &printerInfo)
172 {
173     SAFE_DELETE_ARRAY(printerInfo.printerId);
174     SAFE_DELETE_ARRAY(printerInfo.printerName);
175     SAFE_DELETE_ARRAY(printerInfo.description);
176     SAFE_DELETE_ARRAY(printerInfo.location);
177     SAFE_DELETE_ARRAY(printerInfo.makeAndModel);
178     SAFE_DELETE_ARRAY(printerInfo.printerUri);
179     SAFE_DELETE_ARRAY(printerInfo.detailInfo);
180     ReleaseCapability(printerInfo.capability);
181     ReleaseDefaultValue(printerInfo.defaultValue);
182 }
183 
PageSizeArrayConvert(const OHOS::Print::PrinterCapability & cap,Print_PrinterInfo & nativePrinterInfo)184 void PageSizeArrayConvert(const OHOS::Print::PrinterCapability &cap, Print_PrinterInfo &nativePrinterInfo)
185 {
186     ReleaseCapabilityPageSizes(nativePrinterInfo.capability);
187     std::vector<PrintPageSize> pageSizeVector;
188     std::vector<Print_PageSize> nativePageSizeVector;
189     cap.GetSupportedPageSize(pageSizeVector);
190     for (const auto &pageSize : pageSizeVector) {
191         nativePageSizeVector.push_back({
192             CopyString(pageSize.GetId()),
193             CopyString(pageSize.GetName()),
194             pageSize.GetWidth(),
195             pageSize.GetHeight()
196         });
197     }
198     nativePrinterInfo.capability.supportedPageSizes = CopyArray<Print_PageSize>(nativePageSizeVector,
199         nativePrinterInfo.capability.supportedPageSizesCount);
200     PRINT_HILOGI("nativePageSizeVector size = %{public}zu", nativePageSizeVector.size());
201 }
202 
ParseDefaultPageMargin(const nlohmann::json & cupsOpt,Print_Margin & defaultMargin)203 void ParseDefaultPageMargin(const nlohmann::json &cupsOpt, Print_Margin &defaultMargin)
204 {
205     int leftMargin = 0;
206     int topMargin = 0;
207     int rightMargin = 0;
208     int bottomMargin = 0;
209     if (cupsOpt.contains("media-left-margin-supported") && cupsOpt["media-left-margin-supported"].is_string()) {
210         std::string mediaLeftMargin = cupsOpt["media-left-margin-supported"].get<std::string>();
211         ConvertStringToInt(mediaLeftMargin.c_str(), leftMargin);
212     }
213     if (cupsOpt.contains("media-top-margin-supported") && cupsOpt["media-top-margin-supported"].is_string()) {
214         std::string mediaTopMargin = cupsOpt["media-top-margin-supported"].get<std::string>();
215         ConvertStringToInt(mediaTopMargin.c_str(), topMargin);
216     }
217     if (cupsOpt.contains("media-right-margin-supported") && cupsOpt["media-right-margin-supported"].is_string()) {
218         std::string mediaRightMargin = cupsOpt["media-right-margin-supported"].get<std::string>();
219         ConvertStringToInt(mediaRightMargin.c_str(), rightMargin);
220     }
221     if (cupsOpt.contains("media-bottom-margin-supported") && cupsOpt["media-bottom-margin-supported"].is_string()) {
222         std::string mediaBottomMargin = cupsOpt["media-bottom-margin-supported"].get<std::string>();
223         ConvertStringToInt(mediaBottomMargin.c_str(), bottomMargin);
224     }
225     defaultMargin.leftMargin = static_cast<uint32_t>(leftMargin);
226     defaultMargin.topMargin = static_cast<uint32_t>(topMargin);
227     defaultMargin.rightMargin = static_cast<uint32_t>(rightMargin);
228     defaultMargin.bottomMargin = static_cast<uint32_t>(bottomMargin);
229 }
230 
ParseMediaOpt(const nlohmann::json & cupsOpt,Print_PrinterInfo & nativePrinterInfo)231 void ParseMediaOpt(const nlohmann::json &cupsOpt, Print_PrinterInfo &nativePrinterInfo)
232 {
233     if (cupsOpt.contains("defaultPageSizeId") && cupsOpt["defaultPageSizeId"].is_string()) {
234         std::string defaultPageSizeId = cupsOpt["defaultPageSizeId"].get<std::string>();
235         PRINT_HILOGD("defaultPageSizeId %{public}s", defaultPageSizeId.c_str());
236         nativePrinterInfo.defaultValue.defaultPageSizeId = CopyString(defaultPageSizeId);
237     }
238     if (cupsOpt.contains("media-type-supported") && cupsOpt["media-type-supported"].is_string()) {
239         std::string mediaTypeSupported = cupsOpt["media-type-supported"].get<std::string>();
240         PRINT_HILOGD("cupsOptionsStr media-type-supported %{public}s", mediaTypeSupported.c_str());
241         nativePrinterInfo.capability.supportedMediaTypes = CopyString(mediaTypeSupported);
242     }
243     if (cupsOpt.contains("media-type-default") && cupsOpt["media-type-default"].is_string()) {
244         std::string mediaTypeDefault = cupsOpt["media-type-default"].get<std::string>();
245         PRINT_HILOGD("cupsOptionsStr media-type-default %{public}s", mediaTypeDefault.c_str());
246         nativePrinterInfo.defaultValue.defaultMediaType = CopyString(mediaTypeDefault);
247     }
248     if (cupsOpt.contains("media-source-default") && cupsOpt["media-source-default"].is_string()) {
249         std::string mediaSourceDefault = cupsOpt["media-source-default"].get<std::string>();
250         PRINT_HILOGD("cupsOptionsStr media-source-default %{public}s", mediaSourceDefault.c_str());
251         nativePrinterInfo.defaultValue.defaultPaperSource = CopyString(mediaSourceDefault);
252     }
253     if (cupsOpt.contains("media-source-supported") && cupsOpt["media-source-supported"].is_string()) {
254         std::string mediaSourceSupported = cupsOpt["media-source-supported"].get<std::string>();
255         PRINT_HILOGD("cupsOptionsStr media-source-supported %{public}s", mediaSourceSupported.c_str());
256         nativePrinterInfo.capability.supportedPaperSources = CopyString(mediaSourceSupported);
257     }
258 }
259 
ParseColorModeArray(const nlohmann::json & arrayObject,Print_PrinterInfo & nativePrinterInfo)260 void ParseColorModeArray(const nlohmann::json &arrayObject, Print_PrinterInfo &nativePrinterInfo)
261 {
262     std::vector<uint32_t> list;
263     std::string key = "color";
264     ConvertJsonArrayToIntList(arrayObject, key, list);
265     nativePrinterInfo.capability.supportedColorModes = CopyArray<uint32_t, Print_ColorMode>(
266         list, nativePrinterInfo.capability.supportedColorModesCount, ConvertColorMode);
267 }
268 
ParseDuplexModeArray(const nlohmann::json & arrayObject,Print_PrinterInfo & nativePrinterInfo)269 void ParseDuplexModeArray(const nlohmann::json &arrayObject, Print_PrinterInfo &nativePrinterInfo)
270 {
271     std::vector<uint32_t> list;
272     std::string key = "duplex";
273     ConvertJsonArrayToIntList(arrayObject, key, list);
274     nativePrinterInfo.capability.supportedDuplexModes = CopyArray<uint32_t, Print_DuplexMode>(
275         list, nativePrinterInfo.capability.supportedDuplexModesCount, ConvertDuplexMode);
276 }
277 
ParseQualityArray(const nlohmann::json & arrayObject,Print_PrinterInfo & nativePrinterInfo)278 void ParseQualityArray(const nlohmann::json &arrayObject, Print_PrinterInfo &nativePrinterInfo)
279 {
280     std::vector<uint32_t> list;
281     std::string key = "quality";
282     ConvertJsonArrayToIntList(arrayObject, key, list);
283     nativePrinterInfo.capability.supportedQualities =
284         CopyArray<uint32_t, Print_Quality>(list, nativePrinterInfo.capability.supportedQualitiesCount, ConvertQuality);
285 }
286 
ParseResolutionObject(const nlohmann::json & jsonObject,Print_Resolution & resolution)287 bool ParseResolutionObject(const nlohmann::json &jsonObject, Print_Resolution &resolution)
288 {
289     if (!jsonObject.contains("horizontalDpi")) {
290         PRINT_HILOGW("horizontalDpi missing");
291         return false;
292     }
293     if (!jsonObject["horizontalDpi"].is_number()) {
294         PRINT_HILOGW("horizontalDpi is not string");
295         return false;
296     }
297     int xDpi = jsonObject["horizontalDpi"];
298     if (!jsonObject.contains("verticalDpi")) {
299         PRINT_HILOGW("verticalDpi missing");
300         return false;
301     }
302     if (!jsonObject["verticalDpi"].is_number()) {
303         PRINT_HILOGW("verticalDpi is not string");
304         return false;
305     }
306     int yDpi = jsonObject["verticalDpi"];
307     resolution.horizontalDpi = static_cast<uint32_t>(xDpi);
308     resolution.verticalDpi = static_cast<uint32_t>(yDpi);
309     return true;
310 }
311 
ParseResolutionArray(const nlohmann::json & arrayObject,Print_PrinterInfo & nativePrinterInfo)312 void ParseResolutionArray(const nlohmann::json &arrayObject, Print_PrinterInfo &nativePrinterInfo)
313 {
314     std::vector<Print_Resolution> list;
315     PRINT_HILOGI("ParseResolutionArray arrayObject size = %{public}zu", arrayObject.size());
316     for (auto &item : arrayObject) {
317         Print_Resolution resolution;
318         if (!ParseResolutionObject(item, resolution)) {
319             PRINT_HILOGW("ParseResolutionObject fail");
320             continue;
321         }
322         list.push_back(resolution);
323     }
324     nativePrinterInfo.capability.supportedResolutions =
325         CopyArray<Print_Resolution>(list, nativePrinterInfo.capability.supportedResolutionsCount);
326 }
327 
ParsePrinterOpt(const nlohmann::json & cupsOpt,Print_PrinterInfo & nativePrinterInfo)328 void ParsePrinterOpt(const nlohmann::json &cupsOpt, Print_PrinterInfo &nativePrinterInfo)
329 {
330     if (cupsOpt.contains("printer-location") && cupsOpt["printer-location"].is_string()) {
331         std::string pLocation = cupsOpt["printer-location"].get<std::string>();
332         PRINT_HILOGD("printer-location: %{public}s", pLocation.c_str());
333         nativePrinterInfo.location = CopyString(pLocation);
334     }
335     std::string keyword = "orientation-requested-supported";
336     if (cupsOpt.contains(keyword) && cupsOpt[keyword].is_string()) {
337         std::string orientationArray = cupsOpt[keyword].get<std::string>();
338         PRINT_HILOGD("supported orientations: %{public}s", orientationArray.c_str());
339         std::vector<uint32_t> orientationVector = PrintUtil::Str2Vec(orientationArray);
340         nativePrinterInfo.capability.supportedOrientations = CopyArray<uint32_t, Print_OrientationMode>(
341             orientationVector, nativePrinterInfo.capability.supportedOrientationsCount, ConvertOrientationMode);
342     }
343     keyword = "orientation-requested-default";
344     if (cupsOpt.contains(keyword) && cupsOpt[keyword].is_string()) {
345         std::string orientationString = cupsOpt[keyword].get<std::string>();
346         PRINT_HILOGD("default orientation: %{public}s", orientationString.c_str());
347         int orientationValue = 0;
348         if (ConvertStringToInt(orientationString.c_str(), orientationValue)) {
349             uint32_t defaultOrientation = static_cast<uint32_t>(orientationValue);
350             ConvertOrientationMode(defaultOrientation, nativePrinterInfo.defaultValue.defaultOrientation);
351         }
352     }
353     keyword = "printer-resolution-supported";
354     ParseJsonFieldAsArrayOpt(cupsOpt, keyword, nativePrinterInfo, ParseResolutionArray);
355     keyword = "printer-resolution-default";
356     if (cupsOpt.contains(keyword) && cupsOpt[keyword].is_string()) {
357         std::string resolutionString = cupsOpt[keyword].get<std::string>();
358         if (json::accept(resolutionString)) {
359             nlohmann::json resolutionJson = json::parse(resolutionString);
360             if (!ParseResolutionObject(resolutionJson, nativePrinterInfo.defaultValue.defaultResolution)) {
361                 PRINT_HILOGW("ParseResolutionObject fail");
362             }
363         }
364     }
365     keyword = "print-color-mode-supported";
366     ParseJsonFieldAsArrayOpt(cupsOpt, keyword, nativePrinterInfo, ParseColorModeArray);
367 }
368 
ConvertStringToUint32(const char * src,uint32_t & dst)369 bool ConvertStringToUint32(const char *src, uint32_t &dst)
370 {
371     if (src == nullptr || src[0] == '\0') {
372         return false;
373     }
374     errno = 0;
375     char *endPtr = nullptr;
376     dst = strtoul(src, &endPtr, NUMBER_BASE);
377     if (errno == ERANGE || endPtr == src || *endPtr != '\0') {
378         PRINT_HILOGW("ConvertStringToUint32 fail: %{public}s", src);
379         return false;
380     }
381     return true;
382 }
383 
ParseCupsCopyOpt(const nlohmann::json & cupsOpt,Print_PrinterInfo & nativePrinterInfo)384 void ParseCupsCopyOpt(const nlohmann::json &cupsOpt, Print_PrinterInfo &nativePrinterInfo)
385 {
386     std::string keyword = "sides-supported";
387     ParseJsonFieldAsArrayOpt(cupsOpt, keyword, nativePrinterInfo, ParseDuplexModeArray);
388 
389     keyword = "print-quality-supported";
390     ParseJsonFieldAsArrayOpt(cupsOpt, keyword, nativePrinterInfo, ParseQualityArray);
391     if (cupsOpt.contains("copies-default") && cupsOpt["copies-default"].is_string()) {
392         std::string defaultCopies = cupsOpt["copies-default"].get<std::string>();
393         uint32_t defaultCopiesNum = 0;
394         if (!ConvertStringToUint32(defaultCopies.c_str(), defaultCopiesNum)) {
395             PRINT_HILOGE("copies-default error: %{public}s", defaultCopies.c_str());
396             return;
397         }
398         nativePrinterInfo.defaultValue.defaultCopies = defaultCopiesNum;
399         PRINT_HILOGD("copies-default: %{public}d", defaultCopiesNum);
400     }
401     if (cupsOpt.contains("copies-supported") && cupsOpt["copies-supported"].is_string()) {
402         std::string copySupport = cupsOpt["copies-supported"].get<std::string>();
403         uint32_t copySupportNum = 0;
404         if (!ConvertStringToUint32(copySupport.c_str(), copySupportNum)) {
405             PRINT_HILOGE("copies-supported error: %{public}s", copySupport.c_str());
406             return;
407         }
408         nativePrinterInfo.capability.supportedCopies = copySupportNum;
409         PRINT_HILOGD("copies-supported: %{public}d", copySupportNum);
410     }
411 }
412 
ParseCupsOptions(const nlohmann::json & cupsOpt,Print_PrinterInfo & nativePrinterInfo)413 void ParseCupsOptions(const nlohmann::json &cupsOpt, Print_PrinterInfo &nativePrinterInfo)
414 {
415     ParsePrinterOpt(cupsOpt, nativePrinterInfo);
416     ParseDefaultPageMargin(cupsOpt, nativePrinterInfo.defaultValue.defaultMargin);
417     ParseCupsCopyOpt(cupsOpt, nativePrinterInfo);
418     ParseMediaOpt(cupsOpt, nativePrinterInfo);
419     nlohmann::json advancedCapJson;
420     std::string keyword = "multiple-document-handling-supported";
421     AddJsonFieldStringToJsonObject(cupsOpt, keyword, advancedCapJson);
422     nativePrinterInfo.capability.advancedCapability = CopyString(advancedCapJson.dump().c_str());
423 }
424 
ParseInfoOption(const std::string & infoOption,Print_PrinterInfo & nativePrinterInfo)425 int32_t ParseInfoOption(const std::string &infoOption, Print_PrinterInfo &nativePrinterInfo)
426 {
427     if (!json::accept(infoOption)) {
428         PRINT_HILOGW("infoOption can not parse to json object");
429         return E_PRINT_INVALID_PARAMETER;
430     }
431     nlohmann::json infoJson = json::parse(infoOption);
432     if (!infoJson.contains("printerUri") || !infoJson["printerUri"].is_string() ||
433         !infoJson.contains("make") || !infoJson["make"].is_string()) {
434         PRINT_HILOGW("The infoJson does not have a necessary attribute.");
435         return E_PRINT_INVALID_PARAMETER;
436     }
437     nativePrinterInfo.makeAndModel = CopyString(infoJson["make"].get<std::string>());
438     nativePrinterInfo.printerUri = CopyString(infoJson["printerUri"].get<std::string>());
439     if (!infoJson.contains("cupsOptions")) {
440         PRINT_HILOGW("The infoJson does not have a cupsOptions attribute.");
441         return E_PRINT_NONE;
442     }
443     nlohmann::json cupsOpt = infoJson["cupsOptions"];
444     ParseCupsOptions(cupsOpt, nativePrinterInfo);
445     return E_PRINT_NONE;
446 }
447 
GetSettingItemString(const std::string key,json defaultSetting,json setting)448 std::string GetSettingItemString(const std::string key, json defaultSetting, json setting)
449 {
450     if (setting.contains(key) && setting[key].is_string() && !setting[key].get<std::string>().empty()) {
451         return setting[key].get<std::string>();
452     } else if (defaultSetting.contains(key) && defaultSetting[key].is_string() &&
453                 !defaultSetting[key].get<std::string>().empty()) {
454         return defaultSetting[key].get<std::string>();
455     }
456     if (key == QUALITY_STRING) {
457         return DEFAULT_QUALITY_PREFERENCE;
458     }
459     return "";
460 }
461 
ParsePrinterPreference(const std::string & printerPreference,Print_PrinterInfo & nativePrinterInfo)462 void ParsePrinterPreference(const std::string &printerPreference, Print_PrinterInfo &nativePrinterInfo)
463 {
464     if (!json::accept(printerPreference)) {
465         PRINT_HILOGW("printerPreference can not parse to json object");
466         return;
467     }
468     nlohmann::json preferenceJson = json::parse(printerPreference);
469     if (!preferenceJson.contains("defaultSetting") || !preferenceJson["defaultSetting"].is_object() ||
470         !preferenceJson.contains("setting") || !preferenceJson["setting"].is_object()) {
471         PRINT_HILOGW("The infoJson does not have a necessary attribute.");
472         return;
473     }
474     json defaultSetting = preferenceJson["defaultSetting"];
475     json setting = preferenceJson["setting"];
476 
477     std::string defaultDuplex = GetSettingItemString(DUPLEX_STRING, defaultSetting, setting);
478     int32_t defaultDuplexNum = 0;
479     if (!PrintUtil::ConvertToInt(defaultDuplex, defaultDuplexNum)) {
480         PRINT_HILOGE("defaultDuplex %{public}s can not parse to number", defaultDuplex.c_str());
481         return;
482     }
483     ConvertDuplexMode(defaultDuplexNum, nativePrinterInfo.defaultValue.defaultDuplexMode);
484 
485     std::string defaultOrientation = GetSettingItemString(ORIENTATION_STRING, defaultSetting, setting);
486     int32_t defaultOrientationNum = 0;
487     if (!PrintUtil::ConvertToInt(defaultOrientation, defaultOrientationNum)) {
488         PRINT_HILOGE("%{public}s is incorrectly formatted.", defaultOrientation.c_str());
489         return;
490     }
491     ConvertOrientationMode(defaultOrientationNum, nativePrinterInfo.defaultValue.defaultOrientation);
492 
493     nativePrinterInfo.defaultValue.defaultPageSizeId =
494         CopyString(GetSettingItemString(PAGESIZEID_STRING, defaultSetting, setting));
495 
496     std::string defaultQuality = GetSettingItemString(QUALITY_STRING, defaultSetting, setting);
497     int32_t defaultQualityNum = 0;
498     if (!PrintUtil::ConvertToInt(defaultQuality, defaultQualityNum)) {
499         PRINT_HILOGE("defaultQuality %{public}s can not parse to number", defaultQuality.c_str());
500         return;
501     }
502     ConvertQuality(defaultQualityNum, nativePrinterInfo.defaultValue.defaultPrintQuality);
503 }
504 
ConvertToNativePrinterInfo(const PrinterInfo & info)505 Print_PrinterInfo *ConvertToNativePrinterInfo(const PrinterInfo &info)
506 {
507     Print_PrinterInfo *nativePrinterInfo = new (std::nothrow) Print_PrinterInfo;
508     if (nativePrinterInfo == nullptr) {
509         PRINT_HILOGW("Print_PrinterInfo allocate fail.");
510         return nullptr;
511     }
512     if (memset_s(nativePrinterInfo, sizeof(Print_PrinterInfo), 0, sizeof(Print_PrinterInfo)) != 0) {
513         PRINT_HILOGW("Print_PrinterInfo memset_s fail.");
514         delete nativePrinterInfo;
515         nativePrinterInfo = nullptr;
516         return nullptr;
517     }
518     nativePrinterInfo->printerId = CopyString(info.GetPrinterId());
519     nativePrinterInfo->printerName = CopyString(info.GetPrinterName());
520     nativePrinterInfo->description = CopyString(info.GetDescription());
521     nativePrinterInfo->detailInfo = nullptr;
522     nativePrinterInfo->printerState = static_cast<Print_PrinterState>(info.GetPrinterStatus());
523     if (info.HasIsDefaultPrinter() && info.GetIsDefaultPrinter() == true) {
524         nativePrinterInfo->isDefaultPrinter = true;
525     }
526     OHOS::Print::PrinterCapability cap;
527     info.GetCapability(cap);
528     PageSizeArrayConvert(cap, *nativePrinterInfo);
529     if (cap.HasOption() && json::accept(cap.GetOption())) {
530         nlohmann::json capJson = json::parse(cap.GetOption());
531         if (capJson.contains("cupsOptions") && capJson["cupsOptions"].is_object()) {
532             nlohmann::json cupsJson = capJson["cupsOptions"];
533             ParseCupsOptions(cupsJson, *nativePrinterInfo);
534         }
535     }
536     ConvertColorMode(cap.GetColorMode(), nativePrinterInfo->defaultValue.defaultColorMode);
537     ConvertDuplexMode(cap.GetDuplexMode(), nativePrinterInfo->defaultValue.defaultDuplexMode);
538 
539     std::string printerPreference = "";
540     int32_t ret = PrintManagerClient::GetInstance()->GetPrinterPreference(info.GetPrinterId(), printerPreference);
541     if (ret != E_PRINT_NONE) {
542         PRINT_HILOGW("Print_PrinterInfo GetPrinterPreference fail.");
543     } else {
544         ParsePrinterPreference(printerPreference, *nativePrinterInfo);
545     }
546     if (info.HasOption()) {
547         std::string infoOpt = info.GetOption();
548         PRINT_HILOGW("infoOpt json object: %{public}s", infoOpt.c_str());
549         ParseInfoOption(infoOpt, *nativePrinterInfo);
550     }
551     return nativePrinterInfo;
552 }
553 
SetPrintOrientationInPrintJob(const Print_PrintJob & nativePrintJob,PrintJob & printJob)554 void SetPrintOrientationInPrintJob(const Print_PrintJob &nativePrintJob, PrintJob &printJob)
555 {
556     uint32_t ori = static_cast<uint32_t>(nativePrintJob.orientationMode);
557     if (ori == ORIENTATION_MODE_PORTRAIT || ori == ORIENTATION_MODE_REVERSE_PORTRAIT) {
558         printJob.SetIsLandscape(false);
559         printJob.SetIsSequential(true);
560     } else if (ori == ORIENTATION_MODE_LANDSCAPE || ori == ORIENTATION_MODE_REVERSE_LANDSCAPE) {
561         printJob.SetIsLandscape(true);
562         printJob.SetIsSequential(false);
563     }
564 }
565 
SetPrintMarginInPrintJob(const Print_PrintJob & nativePrintJob,PrintJob & printJob)566 void SetPrintMarginInPrintJob(const Print_PrintJob &nativePrintJob, PrintJob &printJob)
567 {
568     PrintMargin margin;
569     if (nativePrintJob.printMargin.topMargin > 0) {
570         margin.SetTop(nativePrintJob.printMargin.topMargin);
571     } else {
572         margin.SetTop(0);
573     }
574     if (nativePrintJob.printMargin.rightMargin > 0) {
575         margin.SetRight(nativePrintJob.printMargin.rightMargin);
576     } else {
577         margin.SetRight(0);
578     }
579     if (nativePrintJob.printMargin.bottomMargin > 0) {
580         margin.SetBottom(nativePrintJob.printMargin.bottomMargin);
581     } else {
582         margin.SetBottom(0);
583     }
584     if (nativePrintJob.printMargin.leftMargin > 0) {
585         margin.SetLeft(nativePrintJob.printMargin.leftMargin);
586     } else {
587         margin.SetLeft(0);
588     }
589     printJob.SetMargin(margin);
590 }
591 
SetPrintPageSizeInPrintJob(const Print_PrintJob & nativePrintJob,PrintJob & printJob)592 bool SetPrintPageSizeInPrintJob(const Print_PrintJob &nativePrintJob, PrintJob &printJob)
593 {
594     PRINT_HILOGI("SetPrintPageSizeInPrintJob in.");
595     if (nativePrintJob.pageSizeId == nullptr) {
596         PRINT_HILOGW("page size is null.");
597         return false;
598     }
599     std::string pageSizeId(nativePrintJob.pageSizeId);
600     PrintPageSize pageSize;
601     if (!PrintPageSize::FindPageSizeById(pageSizeId, pageSize)) {
602         PRINT_HILOGW("cannot find page size: %{public}s.", pageSizeId.c_str());
603         return false;
604     }
605     printJob.SetPageSize(pageSize);
606     PRINT_HILOGI("SetPrintPageSizeInPrintJob out.");
607     return true;
608 }
609 
SetOptionInPrintJob(const Print_PrintJob & nativePrintJob,PrintJob & printJob)610 void SetOptionInPrintJob(const Print_PrintJob &nativePrintJob, PrintJob &printJob)
611 {
612     PRINT_HILOGI("SetOptionInPrintJob in.");
613     nlohmann::json jsonOptions;
614     if (nativePrintJob.jobName != nullptr) {
615         jsonOptions["jobName"] = std::string(nativePrintJob.jobName);
616     }
617     if (nativePrintJob.mediaType != nullptr) {
618         jsonOptions["mediaType"] = std::string(nativePrintJob.mediaType);
619     }
620     jsonOptions["borderless"] = nativePrintJob.borderless ? "true" : "false";
621     Print_Quality quality = nativePrintJob.printQuality;
622     if (quality > static_cast<Print_Quality>(PRINT_QUALITY_HIGH)
623         || quality < static_cast<Print_Quality>(PRINT_QUALITY_DRAFT)) {
624         quality = static_cast<Print_Quality>(PRINT_QUALITY_NORMAL);
625     }
626     jsonOptions["printQuality"] = quality;
627     jsonOptions["documentFormat"] = GetDocumentFormatString(nativePrintJob.documentFormat);
628     jsonOptions["isAutoRotate"] = nativePrintJob.orientationMode == ORIENTATION_MODE_NONE ? true : false;
629     if (nativePrintJob.advancedOptions != nullptr) {
630         jsonOptions["cupsOptions"] = std::string(nativePrintJob.advancedOptions);
631     }
632     std::string option = jsonOptions.dump();
633     PRINT_HILOGD("SetOptionInPrintJob %{public}s", option.c_str());
634     printJob.SetOption(option);
635     PRINT_HILOGI("SetOptionInPrintJob out.");
636 }
637 
ConvertNativeJobToPrintJob(const Print_PrintJob & nativePrintJob,PrintJob & printJob)638 int32_t ConvertNativeJobToPrintJob(const Print_PrintJob &nativePrintJob, PrintJob &printJob)
639 {
640     if (nativePrintJob.fdList == nullptr || nativePrintJob.copyNumber <= 0) {
641         PRINT_HILOGW("ConvertNativeJobToPrintJob invalid param error.");
642         return E_PRINT_INVALID_PARAMETER;
643     }
644     if (!IsValidString(nativePrintJob.printerId)) {
645         PRINT_HILOGW("ConvertNativeJobToPrintJob string empty error.");
646         return E_PRINT_INVALID_PARAMETER;
647     }
648     std::vector<uint32_t> fdList;
649     for (uint32_t i = 0; i < nativePrintJob.fdListCount; i++) {
650         fdList.emplace_back(nativePrintJob.fdList[i]);
651     }
652     printJob.SetFdList(fdList);
653     printJob.SetPrinterId(std::string(nativePrintJob.printerId));
654     printJob.SetCopyNumber(nativePrintJob.copyNumber);
655     printJob.SetDuplexMode(static_cast<uint32_t>(nativePrintJob.duplexMode));
656     printJob.SetColorMode(static_cast<uint32_t>(nativePrintJob.colorMode));
657 
658     SetPrintOrientationInPrintJob(nativePrintJob, printJob);
659     SetPrintMarginInPrintJob(nativePrintJob, printJob);
660     SetPrintPageSizeInPrintJob(nativePrintJob, printJob);
661     SetOptionInPrintJob(nativePrintJob, printJob);
662     return E_PRINT_NONE;
663 }
664 
ConvertStringVectorToPropertyList(const std::vector<std::string> & valueList,Print_PropertyList * propertyList)665 Print_ErrorCode ConvertStringVectorToPropertyList(const std::vector<std::string> &valueList,
666     Print_PropertyList *propertyList)
667 {
668     if (valueList.size() == 0) {
669         PRINT_HILOGW("empty valueList");
670         return PRINT_ERROR_INVALID_PRINTER;
671     }
672     propertyList->list = new (std::nothrow) Print_Property[valueList.size()];
673     if (propertyList->list == nullptr) {
674         PRINT_HILOGW("propertyList->list is null");
675         return PRINT_ERROR_GENERIC_FAILURE;
676     }
677     if (memset_s(propertyList->list, valueList.size() * sizeof(Print_Property), 0,
678         valueList.size() * sizeof(Print_Property)) != 0) {
679         PRINT_HILOGW("memset_s fail");
680         delete[] propertyList->list;
681         propertyList->list = nullptr;
682         return PRINT_ERROR_GENERIC_FAILURE;
683     }
684     uint32_t count = 0;
685     for (size_t i = 0; i < valueList.size(); i++) {
686         std::string keyVal = valueList[i];
687         auto index = keyVal.find('&');
688         if (index == keyVal.npos) {
689             continue;
690         }
691         propertyList->list[count].key = CopyString(keyVal.substr(0, index));
692         propertyList->list[count].value = CopyString(keyVal.substr(index + 1));
693         count++;
694     }
695     propertyList->count = count;
696     return PRINT_ERROR_NONE;
697 }
698 }  // namespace OHOS::Print
699