1/* 2 * Copyright (c) 2023-2025 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 16import ability from '@ohos.ability.ability'; 17import account_osAccount from '@ohos.account.osAccount'; 18import bundleManager from '@ohos.bundle.bundleManager'; 19import { BusinessError, Callback } from '@ohos.base' 20import common from '@ohos.app.ability.common'; 21import connection from '@ohos.net.connection'; 22import Constants from '../constant'; 23import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 24import dlpPermission from '@ohos.dlpPermission'; 25import emitter from '@ohos.events.emitter'; 26import fileUri from '@ohos.file.fileuri'; 27import fs from '@ohos.file.fs'; 28import GlobalContext from '../GlobalContext'; 29import { HiLog } from '../HiLog'; 30import hiSysEvent from '@ohos.hiSysEvent'; 31import { promptAction, UIContext } from '@kit.ArkUI'; 32import { systemDateTime } from '@kit.BasicServicesKit'; 33import util from '@ohos.util'; 34import Want from '@ohos.app.ability.Want'; 35import zlib from '@ohos.zlib'; 36import Result from '../Result'; 37import { ResultMsg } from '../ResultMsg'; 38import FileUtil from '../external/FileUtil'; 39import FileUtils from './FileUtils'; 40 41const TAG = 'Utils'; 42 43const NET_CAPABILITY_INTERNET: number = 12; 44const NET_CAPABILITY_VALIDATED: number = 16; 45const NET_CAPABILITY_CHECKING_CONNECTIVITY: number = 31; 46const TIME_OUT_SECONDS: number = 3; 47const SLEEP_MILLISECONDS: number = 200; 48 49const DAY_TO_MILLISECOND: number = 1000 * 60 * 60 * 24; 50const MINUTE_TO_MILLISECOND: number = 1000 * 60; 51const SECOND_TO_MILLISECOND: number = 1000; 52const RADIX_HEX: number = 16; 53const SHA256: string = 'SHA256'; 54 55const enum UnitType { 56 DAY_UNIT = 1, 57 MINUTE_UNIT = 2, 58 SECOND_UNIT = 3, 59} 60 61const UNIT_MAP = new Map<number, number>([ 62 [UnitType.DAY_UNIT, DAY_TO_MILLISECOND], 63 [UnitType.MINUTE_UNIT, MINUTE_TO_MILLISECOND], 64 [UnitType.SECOND_UNIT, SECOND_TO_MILLISECOND], 65]); 66 67class ChangeOption { 68 public offset: number = 0 69 public length: number = 0 70} 71 72let defaultDlpProperty: dlpPermission.DLPProperty = { 73 ownerAccount: '', 74 ownerAccountType: dlpPermission.AccountType.DOMAIN_ACCOUNT, 75 authUserList: [], 76 contactAccount: '', 77 offlineAccess: true, 78 ownerAccountID: '', 79 everyoneAccessList: [] 80} 81 82let defaultDlpFile: dlpPermission.DLPFile = { 83 dlpProperty: defaultDlpProperty, 84 recoverDLPFile: async () => { 85 }, 86 closeDLPFile: async () => { 87 }, 88 addDLPLinkFile: async () => { 89 }, 90 stopFuseLink: async () => { 91 }, 92 resumeFuseLink: async () => { 93 }, 94 replaceDLPLinkFile: async () => { 95 }, 96 deleteDLPLinkFile: async () => { 97 } 98}; 99 100let defaultAppInfo: dlpPermission.DLPSandboxInfo = { 101 appIndex: -1, 102 tokenID: -1, 103}; 104 105interface AuthAccount { 106 authAccount: string; 107 textContent?: string; 108} 109 110interface PermissionType { 111 value: Resource; 112 data: string; 113 index: number; 114} 115 116interface DLPInfo { 117 name: string; 118 versionCode: string; 119} 120 121interface DLPGeneralInfo { 122 accountType: number; 123 realFileType: string; 124} 125 126interface BundleNameInfo { 127 callerBundleName: string; 128 sandboxBundleName: string; 129} 130 131function getFileUriByPath(filePath: string): string { 132 try { 133 let uri = fileUri.getUriFromPath(filePath); 134 return uri; 135 } catch (err) { 136 HiLog.error(TAG, `getUriFromPath error: ${JSON.stringify(err)}`); 137 return ''; 138 } 139} 140 141function getFileFd(uri: string, mode?: number): Result<number> { 142 mode = mode || fs.OpenMode.READ_ONLY; 143 try { 144 let file = fs.openSync(uri, mode); 145 HiLog.info(TAG, `open filename: ${FileUtils.getFileNameByUri(uri)}, as: ${file.fd}`); 146 return ResultMsg.buildSuccess(file.fd); 147 } catch (err) { 148 HiLog.wrapError(TAG, err, 'openSync error'); 149 return ResultMsg.getErrMsg(Constants.ERR_CODE_OPEN_FILE_ERROR); 150 } 151} 152 153async function getOsAccountInfo(): Promise<account_osAccount.OsAccountInfo> { 154 let accountMgr = account_osAccount.getAccountManager(); 155 return await accountMgr.queryOsAccount(); 156} 157 158function checkDomainAccountInfo(accountInfo: account_osAccount.OsAccountInfo): Result<void> { 159 AppStorage.setOrCreate('hiAccountType', dlpPermission.AccountType.DOMAIN_ACCOUNT); 160 if (accountInfo.domainInfo.accountName === '' && 161 accountInfo.domainInfo.accountId === '') { 162 AppStorage.setOrCreate('hiAccountStatus', 0); 163 return ResultMsg.getErrMsg(Constants.ERR_JS_APP_NO_ACCOUNT_ERROR); 164 } 165 if (!accountInfo.domainInfo.isAuthenticated) { 166 AppStorage.setOrCreate('hiAccountStatus', 0); 167 return ResultMsg.getErrMsg(Constants.ERR_JS_APP_SYSTEM_IS_AUTHENTICATED); 168 } 169 AppStorage.setOrCreate('hiAccountStatus', 1); 170 return ResultMsg.buildSuccess(); 171} 172 173async function getUserId(): Promise<number> { 174 let accountMgr = account_osAccount.getAccountManager(); 175 return await accountMgr.getOsAccountLocalId(); 176} 177 178function getAuthPerm(accountName: string, dlpProperty: dlpPermission.DLPProperty): dlpPermission.DLPFileAccess { 179 let perm: dlpPermission.DLPFileAccess = dlpPermission.DLPFileAccess.NO_PERMISSION; 180 if (accountName === dlpProperty.ownerAccount) { 181 return dlpPermission.DLPFileAccess.FULL_CONTROL; 182 } 183 if ((dlpProperty.everyoneAccessList !== undefined) && (dlpProperty.everyoneAccessList.length > 0)) { 184 perm = Math.max(...dlpProperty.everyoneAccessList); 185 } 186 let authUserList = dlpProperty.authUserList ?? []; 187 for (let i = 0; i < authUserList.length; ++i) { 188 let authUser = authUserList[i]; 189 if (authUser.authAccount === accountName) { 190 return authUser.dlpFileAccess; 191 } 192 } 193 return perm; 194} 195 196function terminateSelfWithResult(resultCode: number, result: string): void { 197 let abilityResult: ability.AbilityResult = { 198 resultCode: resultCode, 199 want: { 200 parameters: { 201 result: result 202 } 203 } 204 }; 205 try { 206 (getContext() as common.UIAbilityContext).terminateSelfWithResult(abilityResult); 207 } catch (error) { 208 HiLog.error(TAG, `terminateSelfWithResult exception, error is ${JSON.stringify(error)}`); 209 } 210} 211 212function judgeIsSandBox(want: Want) { 213 return new Promise<boolean>(async resolve => { 214 let callerToken: number = want.parameters?.[Constants.PARAMS_CALLER_TOKEN] as number; 215 let callerBundleName: string = want.parameters?.[Constants.PARAMS_CALLER_BUNDLE_NAME] as string; 216 try { 217 let applicationInfo = await bundleManager.getApplicationInfo( 218 callerBundleName, bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT); 219 if (callerToken === applicationInfo.accessTokenId) { 220 resolve(false); 221 return; 222 } 223 } catch (error) { 224 HiLog.error(TAG, `getApplicationInfo exception, error is ${JSON.stringify(error)}`); 225 resolve(false); 226 return; 227 } 228 resolve(true); 229 }) 230} 231 232let removeDuplicate = (arr: AuthAccount[], arg: string) => { 233 let map: Map<string, AuthAccount> = new Map(); 234 for (let item of arr) { 235 if (!map.has(item.authAccount)) { 236 map.set(item.authAccount, item); 237 } 238 } 239 return Array.from<AuthAccount>(map.values()); 240} 241 242 243let calculate = (newValue: Area, allNames: AuthAccount[]) => { 244 let editLength = allNames.length; 245 let screenWidth = Number(newValue['width']); 246 let nameChange = Constants.ENCRYPTION_STAFF_WIDTH_NAME; 247 let rowNamesLen = Math.floor(screenWidth / (nameChange + Constants.ENCRYPTION_ADD_STAFF_MARGIN_RIGHT)); 248 let showNamesArr: AuthAccount[]; 249 if (rowNamesLen === 0) { 250 showNamesArr = []; 251 } else { 252 showNamesArr = editLength > Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen 253 ? allNames.slice(0, 2 * rowNamesLen - 1) 254 : allNames.slice(0, 2 * rowNamesLen); 255 } 256 let hideNamesNum = editLength - showNamesArr.length > 0 257 ? String(editLength - showNamesArr.length) 258 : '0'; 259 return { 260 'rowNamesLen': rowNamesLen, 261 'showNamesArr': showNamesArr, 262 'hideNamesNum': hideNamesNum 263 } as Record<string, number | AuthAccount[] | string> 264} 265 266let toggleShow = (allNames: AuthAccount[], showNamesArr: AuthAccount[], editFlag: boolean, rowNamesLen: number) => { 267 if (showNamesArr.length < allNames.length) { 268 let showFlag = !editFlag; 269 let showNamesArr = allNames; 270 return { 271 'showNamesArr': showNamesArr, 272 'showFlag': showFlag 273 } as Record<string, AuthAccount[] | boolean>; 274 } else { 275 let showFlag = !editFlag; 276 let showNamesArr = allNames.length > Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen 277 ? allNames.slice(0, Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen - 1) 278 : allNames.slice(0, Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen); 279 return { 280 'showNamesArr': showNamesArr, 281 'showFlag': showFlag 282 } as Record<string, AuthAccount[] | boolean>; 283 } 284} 285 286function directionStatus(func: Callback<number>) { 287 let innerEvent: emitter.InnerEvent = { 288 eventId: Constants.ENCRYPTION_EMIT_DIRECTION_STATUS 289 }; 290 emitter.on(innerEvent, (eventData: emitter.EventData) => { 291 func(eventData.data?.direction); 292 }); 293} 294 295function getAppId(bundleName: string) { 296 return new Promise<string>(async (resolve, reject) => { 297 let bundleFlags: number = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO; 298 let userId = await getUserId(); 299 try { 300 let data = await bundleManager.getBundleInfo(bundleName, bundleFlags, userId); 301 if (data.signatureInfo.appId) { 302 resolve(data.signatureInfo.appId); 303 return; 304 } 305 reject(); 306 } catch (err) { 307 HiLog.error(TAG, `get appId failed: ${JSON.stringify(err)}`); 308 reject(); 309 } 310 }) 311} 312 313async function getAppIdWithUserId(bundleName: string, userId: number): Promise<Result<string>> { 314 let bundleFlags: number = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO; 315 try { 316 let data = await bundleManager.getBundleInfo(bundleName, bundleFlags, userId); 317 if (data.signatureInfo.appId) { 318 return ResultMsg.buildSuccess(data.signatureInfo.appId); 319 } 320 } catch (err) { 321 HiLog.wrapError(TAG, err, 'get appId failed'); 322 } 323 return ResultMsg.getErrMsg(Constants.ERR_JS_NOT_AUTHORIZED_APPLICATION); 324} 325 326function getTime() { 327 let permanent: boolean | undefined = AppStorage.get('permanent'); 328 if (permanent) { 329 return $r('app.string.permanently'); 330 } 331 let dateTime: number | undefined = AppStorage.get('validity'); 332 if (dateTime !== undefined) { 333 let date = new Date(dateTime); 334 let year = date.getFullYear(); 335 let month = date.getMonth() + 1; 336 let day = date.getDate(); 337 let hour = date.getHours(); 338 let minute = date.getMinutes(); 339 return `${year}/${month}/${day} ${hour}:${minute}`; 340 } else { 341 return ''; 342 } 343} 344 345async function getFileSizeByUri(uri: string): Promise<number> { 346 let inFile: fs.File | undefined; 347 try { 348 inFile = await fs.open(uri, fs.OpenMode.READ_ONLY); 349 let stat = await fs.stat(inFile.fd); 350 HiLog.info(TAG, `get file info success, the size of file is: ${stat.size}`); 351 return stat.size; 352 } catch (err) { 353 HiLog.error(TAG, `open filename: ${FileUtils.getFileNameByUri(uri)}, failed: ${JSON.stringify(err)}`); 354 return Constants.ERR_CODE_OPEN_FILE_ERROR; 355 } finally { 356 if (inFile) { 357 FileUtil.closeSync(inFile); 358 } 359 } 360} 361 362function getFileSizeByUriSync(uri: string): number { 363 let inFile: fs.File | undefined; 364 try { 365 inFile = fs.openSync(uri, fs.OpenMode.READ_ONLY); 366 let stat = fs.statSync(inFile.fd); 367 return stat.size; 368 } catch (err) { 369 HiLog.error(TAG, `open Syncfilename: ${FileUtils.getFileNameByUri(uri)}, failed: ${JSON.stringify(err)}`); 370 return Constants.ERR_CODE_OPEN_FILE_ERROR; 371 } finally { 372 if (inFile) { 373 FileUtil.closeSync(inFile); 374 } 375 } 376} 377 378async function getDLPInfo(): Promise<Result<DLPInfo>> { 379 let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT; 380 try { 381 const data = await bundleManager.getBundleInfoForSelf(bundleFlags); 382 let dlpInfo: DLPInfo = { 383 name: data.name, 384 versionCode: data.versionCode.toString() 385 }; 386 return ResultMsg.buildSuccess(dlpInfo); 387 } catch (err) { 388 HiLog.wrapError(TAG, err, 'getBundleInfoForSelf failed'); 389 return ResultMsg.getErrMsg(Constants.ERR_CODE_GET_BUNDLE_INFO_ERROR); 390 } 391} 392 393function getBundleNameInfo(callerBundleName: string, openFileBundleName: string): string { 394 const bundleInfo: BundleNameInfo = { 395 callerBundleName: callerBundleName, 396 sandboxBundleName: openFileBundleName 397 }; 398 return JSON.stringify(bundleInfo); 399} 400 401function sendDlpManagerAccountLogin(errorCode: number) { 402 let event: hiSysEvent.SysEventInfo = { 403 domain: 'DLP_UE', 404 name: 'DLP_MANAGER_ACCOUNT_LOGIN', 405 eventType: hiSysEvent?.EventType?.BEHAVIOR, 406 params: { 407 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 408 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 409 'ACCOUNT_TYPE': AppStorage.get('hiAccountType') ?? '', 410 'ACCOUNT_STATUS': AppStorage.get('hiAccountStatus') ?? -1, 411 'LOGIN_FAIL_CODE': errorCode ?? -1, 412 'PKG_NAME': AppStorage.get('hiPkgName') ?? '', 413 } as Record<string, number> 414 }; 415 416 try { 417 hiSysEvent.write(event); 418 } catch (err) { 419 HiLog.error(TAG, 'sendDlpManagerAccountLogin failed'); 420 } 421} 422 423function sendDlpManagerFileConfiguration() { 424 let event: hiSysEvent.SysEventInfo = { 425 domain: 'DLP_UE', 426 name: 'DLP_MANAGER_FILE_CONFIGURATION', 427 eventType: hiSysEvent?.EventType?.BEHAVIOR, 428 params: { 429 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 430 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 431 'OPERATION': AppStorage.get('hiOperation') ?? '', 432 'READ_SCOPE': AppStorage.get('hiReadScope') ?? '', 433 'WRITE_SCOPE': AppStorage.get('hiWriteScope') ?? '', 434 'ADVANCED_SETTINGS': AppStorage.get('hiAdvancedSettings') ?? false, 435 'STORE_PATH': AppStorage.get('hiStorePath') ?? false, 436 'ACCOUNT_VERIFY_SUCC': AppStorage.get('hiAccountVerifySucc') ?? -1, 437 'ACCOUNT_VERIFY_FAIL': AppStorage.get('hiAccountVerifyFail') ?? -1, 438 'VALID_DATE': AppStorage.get('hiValidDate') ?? false, 439 } as Record<string, number> 440 }; 441 442 try { 443 hiSysEvent.write(event); 444 } catch (err) { 445 HiLog.error(TAG, 'sendDlpManagerFileConfiguration failed'); 446 } 447} 448 449function sendDlpFileCreateProperties(accountType: number) { 450 let srcFileTypeArray: string[] = AppStorage.get('hiFileTypeArray') ?? []; 451 let srcFileSizeArray: string[] = AppStorage.get('hiFileSizeArray') ?? []; 452 let dstFileSizeArray: string[] = AppStorage.get('hiPolicySizeEncArray') ?? []; 453 454 let hiPNameId: string = AppStorage.get('hiPNameId') ?? ''; 455 let hiPVersionId: string = AppStorage.get('hiPVersionId') ?? ''; 456 let hiCode: number = AppStorage.get('hiCode') ?? -1; 457 let hiPkgName: string = AppStorage.get('hiPkgName') ?? ''; 458 459 for (let index = 0; index < srcFileTypeArray.length; index++) { 460 let event: hiSysEvent.SysEventInfo = { 461 domain: 'DLP_UE', 462 name: 'DLP_FILE_CREATE_EVENT', 463 eventType: hiSysEvent?.EventType?.BEHAVIOR, 464 params: { 465 'ACCOUNT_TYPE': accountType, 466 'PNAMEID': hiPNameId, 467 'PVERSIONID': hiPVersionId, 468 'CODE': hiCode, 469 'FILE_SIZE': srcFileSizeArray[index], 470 'FILE_TYPE': srcFileTypeArray[index], 471 'POLICY_SIZE_ENC': dstFileSizeArray[index], 472 'PKG_NAME': hiPkgName, 473 } 474 }; 475 476 try { 477 hiSysEvent.write(event); 478 } catch (err) { 479 HiLog.error(TAG, 'sendDlpFileCreateProperties failed'); 480 } 481 } 482} 483 484function sendDlpFileOpenProperties() { 485 let event: hiSysEvent.SysEventInfo = { 486 domain: 'DLP_UE', 487 name: 'DLP_FILE_OPEN_EVENT', 488 eventType: hiSysEvent?.EventType?.BEHAVIOR, 489 params: { 490 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 491 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 492 'CODE': AppStorage.get('hiCode') ?? -1, 493 'SANDBOX_PKGNAME': AppStorage.get('hiSandboxPkgName') ?? '', 494 'SANDBOX_INDEX': AppStorage.get('hiSandboxIndex') ?? -1, 495 'ACCOUNT_TYPE': AppStorage.get('hiAccountType') ?? '', 496 'FILE_SIZE': AppStorage.get('hiFileSize') ?? -1, 497 'POLICY_SIZE_ENC': AppStorage.get('hiPolicySizeEnc') ?? -1, 498 } as Record<string, number> 499 }; 500 501 try { 502 hiSysEvent.write(event); 503 } catch (err) { 504 HiLog.error(TAG, 'sendDlpFileOpenProperties failed'); 505 } 506} 507 508function isValidPath(path: string): boolean { 509 if (path.indexOf('./') !== -1 || path.indexOf('../') !== -1) { 510 return false; 511 } 512 return true; 513} 514 515function getAccountTypeAndRealFileType( 516 context: common.ServiceExtensionContext | common.UIExtensionContext, fd: number): Promise<DLPGeneralInfo> { 517 return new Promise(async (resolve, reject) => { 518 let z = new ArrayBuffer(Constants.HEAD_LENGTH_IN_BYTE); 519 let option: ChangeOption = { offset: 0, length: Constants.HEAD_LENGTH_IN_BYTE }; 520 try { 521 fs.readSync(fd, z, option); 522 } catch (error) { 523 HiLog.error(TAG, `readSync exception, error is ${JSON.stringify(error)}`); 524 reject(); 525 return; 526 } 527 let buf = new Uint32Array(z, 0, Constants.HEAD_LENGTH_IN_U32); 528 if (buf && buf[0] === Constants.DLP_ZIP_MAGIC) { 529 const handleZipFileRet = await handleZipFile(context, fd); 530 if (handleZipFileRet.errcode !== Constants.ERR_CODE_SUCCESS || !handleZipFileRet.result) { 531 HiLog.error(TAG, 'handleNonZipFile error'); 532 reject(); 533 return; 534 } 535 resolve(handleZipFileRet.result); 536 return; 537 } else { 538 const handleNonZipFileRet = await handleNonZipFile(fd, buf); 539 if (handleNonZipFileRet.errcode !== Constants.ERR_CODE_SUCCESS || !handleNonZipFileRet.result) { 540 HiLog.error(TAG, 'handleNonZipFile error'); 541 reject(); 542 return; 543 } 544 resolve(handleNonZipFileRet.result); 545 return; 546 } 547 }) 548} 549 550async function handleZipFile(context: common.ServiceExtensionContext | common.UIExtensionContext, 551 fd: number): Promise<Result<DLPGeneralInfo>> { 552 let random = String(Math.random()).substring(Constants.RAND_START, Constants.RAND_END); 553 let filePath = context.filesDir + '/saveAs' + random; 554 let dirPath = context.filesDir + '/saveAsUnzip' + random; 555 let fileName = dirPath + '/dlp_cert'; 556 let generalInfoPath = dirPath + '/dlp_general_info'; 557 let ff: fs.File | undefined; 558 try { 559 const z = new ArrayBuffer(Constants.HEAD_LENGTH_IN_BYTE); 560 const option: ChangeOption = { offset: 0, length: Constants.HEAD_LENGTH_IN_BYTE }; 561 fs.readSync(fd, z, option); 562 ff = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 563 await fs.copyFile(fd, ff.fd); 564 await fs.mkdir(dirPath); 565 await zlib.decompressFile(filePath, dirPath); 566 let dlpInfo = fs.readTextSync(fileName); 567 let infoArray = dlpInfo.split('accountType'); 568 let type = infoArray[1].slice(Constants.TYPE_START, Constants.TYPE_END); 569 GlobalContext.store('accountType', Number(type)); 570 571 let generalInfo = fs.readTextSync(generalInfoPath); 572 let generalInfoArray = generalInfo.split('realFileType'); 573 let realFileType: string = ''; 574 if (generalInfoArray.length === Constants.NUMBER_TWO) { 575 let realFileTypeStr = generalInfoArray[1].split('\"'); 576 if (realFileTypeStr.length > Constants.NUMBER_TWO) { 577 realFileType = realFileTypeStr[Constants.NUMBER_TWO]; 578 } 579 } 580 581 let result: DLPGeneralInfo = { 582 accountType: Number(type), 583 realFileType: realFileType, 584 } 585 return ResultMsg.buildSuccess(result); 586 } catch (err) { 587 HiLog.wrapError(TAG, err, 'decompressFile error'); 588 return ResultMsg.getErrMsg(err.code, err.message); 589 } finally { 590 FileUtil.closeSync(ff); 591 FileUtil.unlinkSync(filePath); 592 FileUtil.rmdirSync(dirPath); 593 } 594} 595 596async function handleNonZipFile(fd: number, buf: Uint32Array): Promise<Result<DLPGeneralInfo>> { 597 let cert = new ArrayBuffer(buf[Constants.CERT_SIZE]); 598 let certOffset = Constants.CERT_OFFSET_4GB * buf[Constants.CERT_OFFSET + 1] + buf[Constants.CERT_OFFSET]; 599 const option: ChangeOption = { offset: certOffset, length: buf[Constants.CERT_SIZE] }; 600 try { 601 fs.readSync(fd, cert, option); 602 let textDecoder: util.TextDecoder = util.TextDecoder.create('utf-8'); 603 let fdString: string = textDecoder.decodeToString(new Uint8Array(cert), { stream: false }); 604 let infoArray = fdString.split('accountType'); 605 let type = infoArray[1].slice(Constants.TYPE_START, Constants.TYPE_END); 606 GlobalContext.store('accountType', Number(type)); 607 let result: DLPGeneralInfo = { 608 accountType: Number(type), 609 realFileType: '', 610 } 611 return ResultMsg.buildSuccess(result); 612 } catch (err) { 613 HiLog.wrapError(TAG, err, 'getStringFromFd error'); 614 return ResultMsg.getErrMsg(err.code, err.message); 615 } 616} 617 618function getCurrentTime(isNano: boolean = false): number { 619 return systemDateTime.getTime(isNano); 620} 621 622function isExpire(timestamp: number, diff: number, unit: number): boolean { 623 if (isNaN(timestamp) || diff <= 0) { 624 return true; 625 } 626 let multipleMill = UNIT_MAP.get(unit); 627 if (!multipleMill) { 628 HiLog.error(TAG, 'Invalid unit'); 629 return false; 630 } 631 632 let currentTime = getCurrentTime(); 633 const diffMilliSecond = Number(currentTime) - Number(timestamp); 634 const compareDiffSec = diff * multipleMill; 635 return diffMilliSecond > compareDiffSec; 636} 637 638async function sleep(milliSeconds: number): Promise<void> { 639 return new Promise<void>(resolve => setTimeout(resolve, milliSeconds)); 640} 641 642async function getConnectionStatus(exactly: boolean = true): Promise<boolean> { 643 HiLog.info(TAG, `Enter getConnectionStatus, exactly mode: ${exactly}.`); 644 try { 645 const startTime = getCurrentTime(); 646 let net: connection.NetHandle = await connection.getDefaultNet(); 647 648 let capabilities: connection.NetCapabilities = await connection.getNetCapabilities(net); 649 HiLog.info(TAG, `success to get net capabilities, ${JSON.stringify(capabilities)}.`); 650 let networkCap = capabilities.networkCap; 651 652 while (exactly && networkCap?.includes(NET_CAPABILITY_CHECKING_CONNECTIVITY)) { 653 HiLog.info(TAG, 'Checking connectivity...'); 654 if (isExpire(startTime, TIME_OUT_SECONDS, UnitType.SECOND_UNIT)) { 655 HiLog.error(TAG, 'Network connection check failed.'); 656 return false; 657 } 658 await sleep(SLEEP_MILLISECONDS); 659 net = await connection.getDefaultNet(); 660 capabilities = await connection.getNetCapabilities(net); 661 networkCap = capabilities.networkCap; 662 } 663 664 let internetExists = networkCap?.includes(NET_CAPABILITY_INTERNET); 665 let validatedExists = networkCap?.includes(NET_CAPABILITY_VALIDATED); 666 if (internetExists && validatedExists) { 667 HiLog.debug(TAG, 'Net connection is valid.'); 668 return true; 669 } else { 670 HiLog.error(TAG, 'Net connection is invalid.'); 671 } 672 } catch (error) { 673 HiLog.error(TAG, `GetConnectionStatus failed: ${JSON.stringify(error)}`); 674 } 675 return false; 676} 677 678function checkNetworkStatus(): Promise<void> { 679 return new Promise((resolve, reject) => { 680 try { 681 let netHandle = connection.getDefaultNetSync(); 682 connection.getNetCapabilities(netHandle, (error: BusinessError, data: connection.NetCapabilities) => { 683 if (error) { 684 HiLog.error(TAG, `checkNetworkStatus failed: ${JSON.stringify(error)}`); 685 reject(); 686 return; 687 } 688 HiLog.info(TAG, `network success to get data: ${JSON.stringify(data)}`); 689 const result = [connection.NetCap.NET_CAPABILITY_INTERNET, connection.NetCap.NET_CAPABILITY_VALIDATED] 690 .every(element => data.networkCap?.includes(element)); 691 if (result) { 692 resolve(); 693 return; 694 } 695 reject(); 696 }) 697 } catch (error) { 698 reject(); 699 } 700 }) 701} 702 703function isInvalidStr(input: string | null | undefined): boolean { 704 return (input === null || input === undefined || input.trim() === '' || input.length === 0); 705} 706 707function showToast(uiContext: UIContext, msg: Resource | string): void { 708 const currentFontSizeScale = AppStorage.get(Constants.FONT_SIZE_SCALE_KEY) as number ?? 1; 709 let showMode: promptAction.ToastShowMode = promptAction.ToastShowMode.DEFAULT; 710 if (currentFontSizeScale > 1) { 711 showMode = promptAction.ToastShowMode.SYSTEM_TOP_MOST; 712 } 713 uiContext.getPromptAction().showToast({ 714 message: msg, 715 duration: Constants.SHARE_SET_TIMEOUT, 716 showMode: showMode, 717 }); 718} 719 720function logErrorShowToast(context: common.UIAbilityContext | common.UIExtensionContext, logMsg: string, 721 toastMsg: Resource | string): void { 722 HiLog.error(TAG, logMsg); 723 let uiContext = UIContext.createUIContextWithoutWindow(context) as UIContext; 724 showToast(uiContext, toastMsg); 725 UIContext.destroyUIContextWithoutWindow(); 726} 727 728async function getSha256(inputData: Uint8Array): Promise<Uint8Array | null> { 729 if (!inputData || inputData.length === 0) { 730 HiLog.error(TAG, 'getSha256: input is invalid.'); 731 return null; 732 } 733 let messageDig: cryptoFramework.Md; 734 try { 735 messageDig = cryptoFramework.createMd(SHA256); 736 await messageDig.update({ 737 data: inputData 738 }); 739 return (await messageDig.digest()).data; 740 } catch (err) { 741 HiLog.error(TAG, `Generate sha256 failed: ${JSON.stringify(err)}`); 742 } 743 return null; 744} 745 746function generateRandom(length: number): Uint8Array | null { 747 if (length <= Constants.RANDOM_LENGTH_MIN) { 748 HiLog.error(TAG, 'Invalid random number length.'); 749 return null; 750 } 751 try { 752 let rand = cryptoFramework.createRandom(); 753 let result: cryptoFramework.DataBlob = rand.generateRandomSync(length); 754 return result.data; 755 } catch (err) { 756 HiLog.error(TAG, `generate random failed: ${JSON.stringify(err)}`); 757 } 758 return null; 759} 760 761function encodeByBase64(data: Uint8Array): string | null { 762 if (!data || data.byteLength === 0) { 763 HiLog.error(TAG, 'encodeByBase64: input is invalid.'); 764 return null; 765 } 766 let base64 = new util.Base64Helper(); 767 try { 768 return base64.encodeToStringSync(data); 769 } catch (err) { 770 HiLog.error(TAG, 'Encode data failed.'); 771 } 772 return null; 773} 774 775function decodeByBase64(data: string): Uint8Array | null { 776 if (isInvalidStr(data)) { 777 HiLog.error(TAG, 'decodeByBase64: input is invalid.'); 778 return null; 779 } 780 let base64 = new util.Base64Helper(); 781 try { 782 return base64.decodeSync(data); 783 } catch (err) { 784 HiLog.wrapError(TAG, err, 'Decode data failed.'); 785 } 786 return null; 787} 788 789function stringToUint8Array(inputData: string): Uint8Array | null { 790 if (isInvalidStr(inputData)) { 791 HiLog.error(TAG, 'stringToUint8Array: input is invalid.'); 792 return null; 793 } 794 if (inputData.length > Constants.MAX_DATA_LEN) { 795 HiLog.error(TAG, 'stringToUint8Array: input length overflow.'); 796 return null; 797 } 798 let arr: number[] = []; 799 for (let i = 0; i < inputData.length; i++) { 800 arr.push(inputData.charCodeAt(i)); 801 } 802 return new Uint8Array(arr); 803} 804 805function uint8ArrayToString(inputData: Uint8Array): string | null { 806 if (!inputData || inputData.byteLength === 0) { 807 HiLog.error(TAG, 'uint8ArrayToString: input is invalid.'); 808 return null; 809 } 810 if (inputData.length > Constants.MAX_DATA_LEN) { 811 HiLog.error(TAG, 'uint8ArrayToString: input length overflow.'); 812 return null; 813 } 814 let dataString: string = ''; 815 for (let i = 0; i < inputData.length; i++) { 816 dataString += String.fromCharCode(inputData[i]); 817 } 818 return dataString; 819} 820 821function uint8ArrayToHexString(inputData: Uint8Array): string | null { 822 if (!inputData || inputData.byteLength === 0) { 823 HiLog.error(TAG, 'uint8ArrayToHexString: input is invalid.'); 824 return null; 825 } 826 if (inputData.length > Constants.MAX_DATA_LEN) { 827 HiLog.error(TAG, 'uint8ArrayToHexString: input length overflow.'); 828 return null; 829 } 830 let hexString: string = ''; 831 for (let i = 0; i < inputData.length; i++) { 832 const hex = inputData[i].toString(RADIX_HEX); 833 hexString += (hex.length === 1 ? '0' + hex : hex); 834 } 835 return hexString; 836} 837 838function getCostTime(startTime: number | undefined): number | undefined { 839 HiLog.info(TAG, 'Start getting cost time.'); 840 if (startTime === undefined || isNaN(startTime)) { 841 HiLog.error(TAG, 'The start time is invalid.'); 842 return undefined; 843 } 844 return systemDateTime.getTime(false) - startTime; 845} 846 847function anonymizeUid(uid: string): string | undefined { 848 if (isInvalidStr(uid)) { 849 HiLog.error(TAG, 'The uid is invalid.'); 850 return undefined; 851 } 852 let anonymizedUid: string = uid.substring(0, Constants.VALID_UID_PREFIX_LENGTH); 853 for (let i = 0; i < uid.length - Constants.VALID_UID_PREFIX_LENGTH; i++) { 854 anonymizedUid += '*'; 855 } 856 return anonymizedUid; 857} 858 859export { 860 AuthAccount, 861 PermissionType, 862 getOsAccountInfo, 863 checkDomainAccountInfo, 864 getUserId, 865 getAuthPerm, 866 terminateSelfWithResult, 867 judgeIsSandBox, 868 getFileFd, 869 getFileUriByPath, 870 removeDuplicate, 871 calculate, 872 toggleShow, 873 directionStatus, 874 getAppId, 875 getCurrentTime, 876 getTime, 877 getFileSizeByUri, 878 getFileSizeByUriSync, 879 getDLPInfo, 880 sendDlpManagerAccountLogin, 881 sendDlpManagerFileConfiguration, 882 sendDlpFileCreateProperties, 883 sendDlpFileOpenProperties, 884 DLPInfo, 885 DLPGeneralInfo, 886 isInvalidStr, 887 isValidPath, 888 defaultDlpFile, 889 getAccountTypeAndRealFileType, 890 checkNetworkStatus, 891 getConnectionStatus, 892 showToast, 893 logErrorShowToast, 894 defaultAppInfo, 895 getAppIdWithUserId, 896 getSha256, 897 generateRandom, 898 encodeByBase64, 899 decodeByBase64, 900 stringToUint8Array, 901 uint8ArrayToString, 902 uint8ArrayToHexString, 903 getCostTime, 904 anonymizeUid, 905 getBundleNameInfo 906}; 907