1 /*
2 * Copyright (c) 2022 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 "napi_print_utils.h"
17
18 #include "ability.h"
19 #include "accesstoken_kit.h"
20 #include "napi_base_context.h"
21 #include "print_constant.h"
22 #include "print_log.h"
23 #include "securec.h"
24 #include "tokenid_kit.h"
25
26 namespace OHOS::Print {
27 static constexpr const int MAX_STRING_LENGTH = 65536;
28 const std::map<int32_t, std::string> ERROR_CODE_CONVERT_MESSAGE_MAP = {
29 {E_PRINT_NO_PERMISSION, "the application does not have permission to call this function."},
30 {E_PRINT_ILLEGAL_USE_OF_SYSTEM_API, "not system application."},
31 {E_PRINT_INVALID_PARAMETER,
32 "Parameter error. Possible causes: 1.Mandatory parameters are left unspecified; 2.Incorrect parameter types."},
33 {E_PRINT_GENERIC_FAILURE, "Generic failure of print."},
34 {E_PRINT_RPC_FAILURE, "RPC failure."},
35 {E_PRINT_SERVER_FAILURE, "Failure of print service."},
36 {E_PRINT_INVALID_EXTENSION, "Invalid print extension."},
37 {E_PRINT_INVALID_PRINTER, "Invalid printer."},
38 {E_PRINT_INVALID_PRINTJOB, "Invalid print job."},
39 {E_PRINT_FILE_IO, "File i/o error."},
40 {E_PRINT_INVALID_TOKEN, "Invalid token."},
41 {E_PRINT_INVALID_USERID, "Invalid user id."},
42 {E_PRINT_TOO_MANY_FILES, "Number of files exceeding the upper limit."},
43 };
44 static const std::string ERROR_MESSAGE_OUT_OF_DEFINITION = "error is out of definition.";
45
GetValueType(napi_env env,napi_value value)46 napi_valuetype NapiPrintUtils::GetValueType(napi_env env, napi_value value)
47 {
48 if (value == nullptr) {
49 return napi_undefined;
50 }
51
52 napi_valuetype valueType = napi_undefined;
53 PRINT_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
54 return valueType;
55 }
56
57 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)58 bool NapiPrintUtils::HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
59 {
60 if (object == nullptr) {
61 return false;
62 }
63 bool hasProperty = false;
64 PRINT_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
65 return hasProperty;
66 }
67
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)68 napi_value NapiPrintUtils::GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
69 {
70 if (object == nullptr) {
71 return nullptr;
72 }
73 napi_value value = nullptr;
74 bool hasProperty = false;
75 PRINT_CALL(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty));
76 if (!hasProperty) {
77 return value;
78 }
79 PRINT_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
80 return value;
81 }
82
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)83 void NapiPrintUtils::SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
84 {
85 if (object == nullptr) {
86 return;
87 }
88 (void)napi_set_named_property(env, object, name.c_str(), value);
89 }
90
GetPropertyNames(napi_env env,napi_value object)91 std::vector<std::string> NapiPrintUtils::GetPropertyNames(napi_env env, napi_value object)
92 {
93 std::vector<std::string> ret;
94 if (object == nullptr) {
95 return ret;
96 }
97 napi_value names = nullptr;
98 PRINT_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
99 uint32_t length = 0;
100 PRINT_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
101 for (uint32_t index = 0; index < length; ++index) {
102 napi_value name = nullptr;
103 if (napi_get_element(env, names, index, &name) != napi_ok) {
104 continue;
105 }
106 if (GetValueType(env, name) != napi_string) {
107 continue;
108 }
109 ret.emplace_back(GetStringFromValueUtf8(env, name));
110 }
111 return ret;
112 }
113
114 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)115 napi_value NapiPrintUtils::CreateUint32(napi_env env, uint32_t code)
116 {
117 napi_value value = nullptr;
118 if (napi_create_uint32(env, code, &value) != napi_ok) {
119 return nullptr;
120 }
121 return value;
122 }
123
GetUint32FromValue(napi_env env,napi_value value)124 uint32_t NapiPrintUtils::GetUint32FromValue(napi_env env, napi_value value)
125 {
126 if (value == nullptr) {
127 return 0;
128 }
129 uint32_t ret = 0;
130 PRINT_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
131 return ret;
132 }
133
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)134 uint32_t NapiPrintUtils::GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
135 {
136 if (object == nullptr) {
137 return 0;
138 }
139 if (!HasNamedProperty(env, object, propertyName)) {
140 return 0;
141 }
142 napi_value value = GetNamedProperty(env, object, propertyName);
143 return GetUint32FromValue(env, value);
144 }
145
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)146 void NapiPrintUtils::SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
147 {
148 if (object == nullptr) {
149 return;
150 }
151 napi_value jsValue = CreateUint32(env, value);
152 if (GetValueType(env, jsValue) != napi_number) {
153 return;
154 }
155
156 napi_set_named_property(env, object, name.c_str(), jsValue);
157 }
158
159 /* INT32 */
CreateInt32(napi_env env,int32_t code)160 napi_value NapiPrintUtils::CreateInt32(napi_env env, int32_t code)
161 {
162 napi_value value = nullptr;
163 if (napi_create_int32(env, code, &value) != napi_ok) {
164 return nullptr;
165 }
166 return value;
167 }
168
GetInt32FromValue(napi_env env,napi_value value)169 int32_t NapiPrintUtils::GetInt32FromValue(napi_env env, napi_value value)
170 {
171 if (value == nullptr) {
172 return 0;
173 }
174 int32_t ret = 0;
175 PRINT_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
176 return ret;
177 }
178
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)179 int32_t NapiPrintUtils::GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
180 {
181 if (object == nullptr) {
182 return 0;
183 }
184 if (!HasNamedProperty(env, object, propertyName)) {
185 return 0;
186 }
187 napi_value value = GetNamedProperty(env, object, propertyName);
188 return GetInt32FromValue(env, value);
189 }
190
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)191 void NapiPrintUtils::SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
192 {
193 if (object == nullptr) {
194 return;
195 }
196 napi_value jsValue = CreateInt32(env, value);
197 if (GetValueType(env, jsValue) != napi_number) {
198 return;
199 }
200
201 napi_set_named_property(env, object, name.c_str(), jsValue);
202 }
203
204 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)205 napi_value NapiPrintUtils::CreateStringUtf8(napi_env env, const std::string &str)
206 {
207 napi_value value = nullptr;
208 if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
209 return nullptr;
210 }
211 return value;
212 }
213
GetStringFromValueUtf8(napi_env env,napi_value value)214 std::string NapiPrintUtils::GetStringFromValueUtf8(napi_env env, napi_value value)
215 {
216 if (value == nullptr) {
217 return "";
218 }
219 std::string result;
220 std::vector<char> str(MAX_STRING_LENGTH + 1, '\0');
221 size_t length = 0;
222 PRINT_CALL_BASE(env, napi_get_value_string_utf8(env, value, &str[0], MAX_STRING_LENGTH, &length), result);
223 if (length > 0) {
224 return result.append(&str[0], length);
225 }
226 return result;
227 }
228
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)229 std::string NapiPrintUtils::GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
230 {
231 if (object == nullptr) {
232 return "";
233 }
234 if (!HasNamedProperty(env, object, propertyName)) {
235 return "";
236 }
237 napi_value value = GetNamedProperty(env, object, propertyName);
238 return GetStringFromValueUtf8(env, value);
239 }
240
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)241 void NapiPrintUtils::SetStringPropertyUtf8(
242 napi_env env, napi_value object, const std::string &name, const std::string &value)
243 {
244 if (object == nullptr) {
245 return;
246 }
247 napi_value jsValue = CreateStringUtf8(env, value);
248 if (GetValueType(env, jsValue) != napi_string) {
249 return;
250 }
251 napi_set_named_property(env, object, name.c_str(), jsValue);
252 }
253
254 /* array buffer */
255
CreateArrayBuffer(napi_env env,size_t length,void ** data)256 napi_value NapiPrintUtils::CreateArrayBuffer(napi_env env, size_t length, void **data)
257 {
258 napi_value object = nullptr;
259 PRINT_CALL(env, napi_create_arraybuffer(env, length, data, &object));
260 return object;
261 }
262
ValueIsArrayBuffer(napi_env env,napi_value value)263 bool NapiPrintUtils::ValueIsArrayBuffer(napi_env env, napi_value value)
264 {
265 if (value == nullptr) {
266 return false;
267 }
268 bool isArrayBuffer = false;
269 PRINT_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
270 return isArrayBuffer;
271 }
272
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)273 void *NapiPrintUtils::GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
274 {
275 if (value == nullptr || length == nullptr) {
276 return nullptr;
277 }
278
279 void *data = nullptr;
280 PRINT_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
281 return data;
282 }
283
284 /* object */
CreateObject(napi_env env)285 napi_value NapiPrintUtils::CreateObject(napi_env env)
286 {
287 napi_value object = nullptr;
288 PRINT_CALL(env, napi_create_object(env, &object));
289 return object;
290 }
291
292 /* undefined */
GetUndefined(napi_env env)293 napi_value NapiPrintUtils::GetUndefined(napi_env env)
294 {
295 napi_value undefined = nullptr;
296 PRINT_CALL(env, napi_get_undefined(env, &undefined));
297 return undefined;
298 }
299
300 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)301 napi_value NapiPrintUtils::CallFunction(
302 napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
303 {
304 if (func == nullptr) {
305 return nullptr;
306 }
307 napi_value res = nullptr;
308 PRINT_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
309 return res;
310 }
311
CreateFunction(napi_env env,const std::string & name,napi_callback func,void * arg)312 napi_value NapiPrintUtils::CreateFunction
313 (napi_env env, const std::string &name, napi_callback func, void *arg)
314 {
315 napi_value res = nullptr;
316 PRINT_CALL(env, napi_create_function(env, name.c_str(), NAPI_AUTO_LENGTH, func, arg, &res));
317 return res;
318 }
319
320 /* reference */
CreateReference(napi_env env,napi_value callback)321 napi_ref NapiPrintUtils::CreateReference(napi_env env, napi_value callback)
322 {
323 if (callback == nullptr) {
324 return nullptr;
325 }
326 napi_ref callbackRef = nullptr;
327 PRINT_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
328 return callbackRef;
329 }
330
GetReference(napi_env env,napi_ref callbackRef)331 napi_value NapiPrintUtils::GetReference(napi_env env, napi_ref callbackRef)
332 {
333 if (callbackRef == nullptr) {
334 return nullptr;
335 }
336 napi_value callback = nullptr;
337 PRINT_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
338 return callback;
339 }
340
DeleteReference(napi_env env,napi_ref callbackRef)341 void NapiPrintUtils::DeleteReference(napi_env env, napi_ref callbackRef)
342 {
343 (void)napi_delete_reference(env, callbackRef);
344 }
345
346 /* boolean */
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)347 bool NapiPrintUtils::GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
348 {
349 if (object == nullptr) {
350 return false;
351 }
352 if (!HasNamedProperty(env, object, propertyName)) {
353 return false;
354 }
355 napi_value value = GetNamedProperty(env, object, propertyName);
356 bool ret = false;
357 PRINT_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
358 return ret;
359 }
360
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)361 void NapiPrintUtils::SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
362 {
363 if (object == nullptr) {
364 return;
365 }
366 napi_value jsValue = nullptr;
367 PRINT_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
368 if (GetValueType(env, jsValue) != napi_boolean) {
369 return;
370 }
371
372 napi_set_named_property(env, object, name.c_str(), jsValue);
373 }
374
375 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)376 void NapiPrintUtils::DefineProperties(
377 napi_env env, napi_value object, const std::initializer_list<napi_property_descriptor> &properties)
378 {
379 std::vector<napi_property_descriptor> descriptors(properties.begin(), properties.end());
380
381 (void)napi_define_properties(env, object, properties.size(), descriptors.data());
382 }
383
GetValueString(napi_env env,napi_value value)384 std::string NapiPrintUtils::GetValueString(napi_env env, napi_value value)
385 {
386 if (value == nullptr) {
387 return "";
388 }
389 std::string resultValue = "";
390 char value_string[256] = { 0 };
391 size_t value_size = 256;
392 size_t result = 0;
393 napi_status status = napi_get_value_string_utf8(env, value, value_string, value_size, &result);
394 if (status == napi_ok && result > 0) {
395 resultValue = value_string;
396 }
397 return resultValue;
398 }
399
GetJsVal(napi_env env,napi_callback_info info,napi_value argv[],size_t length)400 size_t NapiPrintUtils::GetJsVal(napi_env env, napi_callback_info info, napi_value argv[], size_t length)
401 {
402 size_t argc = length;
403 napi_value thisVal = nullptr;
404 void *data = nullptr;
405 napi_get_cb_info(env, info, &argc, argv, &thisVal, &data);
406 return argc;
407 }
408
VerifyProperty(std::vector<std::string> & names,std::map<std::string,PrintParamStatus> & propertyList)409 bool NapiPrintUtils::VerifyProperty(
410 std::vector<std::string> &names, std::map<std::string, PrintParamStatus> &propertyList)
411 {
412 for (const auto& name : names) {
413 if (propertyList.find(name) == propertyList.end()) {
414 PRINT_HILOGE("Invalid property: %{public}s", name.c_str());
415 return false;
416 }
417 propertyList[name] = PRINT_PARAM_SET;
418 }
419
420 for (const auto& propertyItem : propertyList) {
421 if (propertyItem.second == PRINT_PARAM_NOT_SET) {
422 PRINT_HILOGE("Missing Property: %{public}s", propertyItem.first.c_str());
423 return false;
424 }
425 }
426 return true;
427 }
428
GetPrintErrorMsg(int32_t errorCode)429 std::string NapiPrintUtils::GetPrintErrorMsg(int32_t errorCode)
430 {
431 auto msg = PRINT_ERROR_MSG_MAP.find(static_cast<PrintErrorCode>(errorCode));
432 if (msg != PRINT_ERROR_MSG_MAP.end()) {
433 return msg->second;
434 }
435 return "";
436 }
437
CheckCallerIsSystemApp()438 bool NapiPrintUtils::CheckCallerIsSystemApp()
439 {
440 auto callerToken = IPCSkeleton::GetCallingTokenID();
441 auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
442 if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
443 tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
444 PRINT_HILOGD("tokenType check passed.");
445 return true;
446 }
447 auto accessTokenId = IPCSkeleton::GetCallingFullTokenID();
448 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenId);
449 }
450
GetErrorMsgByErrorCode(int32_t code)451 const std::string NapiPrintUtils::GetErrorMsgByErrorCode(int32_t code)
452 {
453 PRINT_HILOGD("GetErrorMsgByErrorCode start");
454 auto iter = ERROR_CODE_CONVERT_MESSAGE_MAP.find(code);
455 if (iter == ERROR_CODE_CONVERT_MESSAGE_MAP.end()) {
456 PRINT_HILOGE("error is out of definition.");
457 return ERROR_MESSAGE_OUT_OF_DEFINITION;
458 }
459 PRINT_HILOGD("ErrorMessage: %{public}s", (iter->second).c_str());
460 return iter->second;
461 }
462
CreateJsError(napi_env env,int32_t errCode)463 napi_value NapiPrintUtils::CreateJsError(napi_env env, int32_t errCode)
464 {
465 std::string errMsg = GetErrorMsgByErrorCode(errCode);
466 PRINT_HILOGD("CreateJsError errCode: %{public}d, errMsg: %{public}s", errCode, errMsg.c_str());
467
468 napi_value code = nullptr;
469 napi_status status = napi_create_int32(env, errCode, &code);
470 if (status != napi_ok) {
471 PRINT_HILOGE("napi create error code failed");
472 return nullptr;
473 }
474
475 napi_value message = nullptr;
476 status = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
477 if (status != napi_ok) {
478 PRINT_HILOGE("napi create error message failed");
479 return nullptr;
480 }
481
482 napi_value errorObj = nullptr;
483 status = napi_create_error(env, code, message, &errorObj);
484 if (status != napi_ok) {
485 PRINT_HILOGE("napi create js error failed");
486 return nullptr;
487 }
488
489 return errorObj;
490 }
491 } // namespace OHOS::Print
492