1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import measure from '@ohos.measure'; 17import window from '@ohos.window'; 18import ability from '@ohos.ability.ability'; 19import account_osAccount from '@ohos.account.osAccount'; 20import emitter from '@ohos.events.emitter'; 21import dlpPermission from '@ohos.dlpPermission'; 22import bundleManager from '@ohos.bundle.bundleManager'; 23import fs from '@ohos.file.fs'; 24import zlib from '@ohos.zlib'; 25import util from '@ohos.util'; 26import fileUri from '@ohos.file.fileuri'; 27import { BusinessError, Callback } from '@ohos.base' 28import Want from '@ohos.app.ability.Want'; 29import common from '@ohos.app.ability.common'; 30import connection from '@ohos.net.connection'; 31import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession'; 32import Constants from '../common/constant'; 33import GlobalContext from './GlobalContext'; 34import hiSysEvent from '@ohos.hiSysEvent'; 35import { HiLog } from '../common/HiLog'; 36 37const TAG = 'Utils'; 38const HEAD_LENGTH_IN_BYTE = 28; 39const HEAD_LENGTH_IN_U32 = 7; 40const CERT_OFFSET = 5; 41const CERT_SIZE = 6; 42class ChangeOption { 43 public offset: number = 0 44 public length: number = 0 45} 46let defaultDlpProperty: dlpPermission.DLPProperty = { 47 ownerAccount: '', 48 ownerAccountType: dlpPermission.AccountType.DOMAIN_ACCOUNT, 49 authUserList: [], 50 contactAccount: '', 51 offlineAccess: true, 52 ownerAccountID: '', 53 everyoneAccessList: [] 54} 55 56let defaultDlpFile: dlpPermission.DLPFile = { 57 dlpProperty: defaultDlpProperty, 58 recoverDLPFile: async () => {}, 59 closeDLPFile: async () => {}, 60 addDLPLinkFile: async () => {}, 61 stopFuseLink: async () => {}, 62 resumeFuseLink: async () => {}, 63 replaceDLPLinkFile: async () => {}, 64 deleteDLPLinkFile: async () => {} 65}; 66 67interface AuthAccount { 68 authAccount: string; 69 textContent?: string; 70} 71 72interface PermissionType { 73 value: Resource; 74 data: string; 75 index: number; 76} 77 78interface DLPInfo { 79 name: string; 80 versionCode: string; 81} 82 83function getFileUriByPath(filePath: string): string { 84 try { 85 let uri = fileUri.getUriFromPath(filePath); 86 return uri; 87 } catch (err) { 88 HiLog.info(TAG, `getUriFromPath error: ${JSON.stringify(err)}`); 89 return ''; 90 } 91} 92 93function getFileFd(uri: string, mode?: number): number { 94 mode = mode || fs.OpenMode.READ_ONLY; 95 try { 96 let file = fs.openSync(uri, mode); 97 HiLog.info(TAG, `open: ${uri}, as: ${file.fd}`); 98 return file.fd; 99 } catch (err) { 100 HiLog.info(TAG, `openSync error: ${JSON.stringify(err)}`); 101 return -1; 102 } 103} 104 105async function getOsAccountInfo(): Promise<account_osAccount.OsAccountInfo> { 106 let accountMgr = account_osAccount.getAccountManager(); 107 return await accountMgr.queryOsAccount(); 108} 109 110function checkDomainAccountInfo(accountInfo: account_osAccount.OsAccountInfo): number { 111 AppStorage.setOrCreate('hiAccountType', dlpPermission.AccountType.DOMAIN_ACCOUNT); 112 if (accountInfo.domainInfo.accountName === '' && 113 accountInfo.domainInfo.accountId === '') { 114 AppStorage.setOrCreate('hiAccountStatus', 0); 115 return Constants.ERR_JS_APP_NO_ACCOUNT_ERROR; 116 } 117 if (!accountInfo.domainInfo.isAuthenticated) { 118 AppStorage.setOrCreate('hiAccountStatus', 0); 119 return Constants.ERR_JS_APP_SYSTEM_IS_AUTHENTICATED; 120 } 121 AppStorage.setOrCreate('hiAccountStatus', 1); 122 return Constants.ERR_JS_APP_ACCOUNT_INFO; 123} 124 125async function getUserId(): Promise<number> { 126 let accountMgr = account_osAccount.getAccountManager(); 127 return await accountMgr.getOsAccountLocalId(); 128} 129 130function getAuthPerm(accountName: string, dlpProperty: dlpPermission.DLPProperty): dlpPermission.DLPFileAccess { 131 let perm: dlpPermission.DLPFileAccess = dlpPermission.DLPFileAccess.NO_PERMISSION; 132 if (accountName === dlpProperty.ownerAccount) { 133 return dlpPermission.DLPFileAccess.FULL_CONTROL; 134 } 135 if ((dlpProperty.everyoneAccessList !== undefined) && (dlpProperty.everyoneAccessList.length > 0)) { 136 perm = Math.max(...dlpProperty.everyoneAccessList); 137 } 138 let authUserList = dlpProperty.authUserList ?? []; 139 for (let i = 0; i < authUserList.length; ++i) { 140 let authUser = authUserList[i]; 141 if (authUser.authAccount === accountName) { 142 return authUser.dlpFileAccess; 143 } 144 } 145 return perm; 146} 147 148function terminateSelfWithResult(resultCode: number, result: string): void { 149 let abilityResult: ability.AbilityResult = { 150 resultCode: resultCode, 151 want: { 152 parameters: { 153 result: result 154 } 155 } 156 }; 157 (getContext() as common.UIAbilityContext).terminateSelfWithResult(abilityResult); 158} 159 160function judgeIsSandBox(want: Want) { 161 return new Promise<boolean>(async resolve => { 162 let callerToken: number = want.parameters?.['ohos.aafwk.param.callerToken'] as number; 163 let callerBundleName: string = want.parameters?.['ohos.aafwk.param.callerBundleName'] as string; 164 let applicationInfo = await bundleManager.getApplicationInfo( 165 callerBundleName, bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT); 166 if (callerToken === applicationInfo.accessTokenId) { 167 resolve(false); 168 } 169 resolve(true); 170 }) 171} 172 173let removeDuplicate = (arr: AuthAccount[], arg: string) => { 174 let map: Map<string, AuthAccount> = new Map(); 175 for (let item of arr) { 176 if (!map.has(item.authAccount)) { 177 map.set(item.authAccount, item); 178 } 179 } 180 return Array.from<AuthAccount>(map.values()); 181} 182 183 184let calculate = (newValue: Area, allNames: AuthAccount[]) => { 185 let editLength = allNames.length; 186 let screenWidth = Number(newValue['width']); 187 let nameChange = Constants.ENCRYPTION_STAFF_WIDTH_NAME; 188 let rowNamesLen = Math.floor(screenWidth / (nameChange + Constants.ENCRYPTION_ADD_STAFF_MARGIN_RIGHT)); 189 let showNamesArr = editLength > Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen 190 ? allNames.slice(0, 2 * rowNamesLen - 1) 191 : allNames.slice(0, 2 * rowNamesLen); 192 let hideNamesNum = editLength - showNamesArr.length > 0 193 ? String(editLength - showNamesArr.length) 194 : '0'; 195 return { 196 'rowNamesLen': rowNamesLen, 197 'showNamesArr': showNamesArr, 198 'hideNamesNum': hideNamesNum 199 } as Record<string, number | AuthAccount[] | string> 200} 201 202let toggleShow = (allNames: AuthAccount[], showNamesArr: AuthAccount[], editFlag: boolean, rowNamesLen: number) => { 203 if (showNamesArr.length < allNames.length) { 204 let showFlag = !editFlag; 205 let showNamesArr = allNames; 206 return { 207 'showNamesArr': showNamesArr, 208 'showFlag': showFlag 209 } as Record<string, AuthAccount[] | boolean>; 210 } else { 211 let showFlag = !editFlag; 212 let showNamesArr = allNames.length > Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen 213 ? allNames.slice(0, Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen - 1) 214 : allNames.slice(0, Constants.ENCRYPTION_DOUBLED_NUMBER * rowNamesLen); 215 return { 216 'showNamesArr': showNamesArr, 217 'showFlag': showFlag 218 } as Record<string, AuthAccount[] | boolean>; 219 } 220} 221 222function directionStatus(func: Callback<number>) { 223 let innerEvent: emitter.InnerEvent = { 224 eventId: Constants.ENCRYPTION_EMIT_DIRECTION_STATUS 225 }; 226 emitter.on(innerEvent, (eventData: emitter.EventData) => { 227 func(eventData.data?.direction); 228 }); 229} 230 231function getAppId(bundleName: string) { 232 return new Promise<string>(async (resolve, reject) => { 233 let bundleFlags: number = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO; 234 let userId = await getUserId(); 235 try { 236 let data = await bundleManager.getBundleInfo(bundleName, bundleFlags, userId); 237 if (data.signatureInfo.appId) { 238 resolve(data.signatureInfo.appId); 239 return; 240 } 241 reject(); 242 } catch (err) { 243 HiLog.error(TAG, `get appId failed: ${JSON.stringify(err)}`); 244 reject(); 245 } 246 }) 247} 248 249function getTime() { 250 let permanent: boolean | undefined = AppStorage.get('permanent'); 251 if (permanent) { 252 return $r('app.string.permanently'); 253 } 254 let dateTime: number | undefined = AppStorage.get('validity'); 255 if (dateTime !== undefined) { 256 let date = new Date(dateTime); 257 let year = date.getFullYear(); 258 let month = date.getMonth() + 1; 259 let day = date.getDate(); 260 let hour = date.getHours(); 261 let minute = date.getMinutes(); 262 return `${year}/${month}/${day} ${hour}:${minute}`; 263 } else { 264 return ''; 265 } 266} 267 268async function getFileSizeByUri(uri: string): Promise<number> { 269 let inFile: fs.File | undefined; 270 try { 271 inFile = await fs.open(uri, fs.OpenMode.READ_ONLY); 272 let stat = await fs.stat(inFile.fd); 273 HiLog.info(TAG, `get file info succeed, the size of file is: ${stat.size}`); 274 return stat.size; 275 } catch (err) { 276 HiLog.error(TAG, `open: ${uri}, failed: ${JSON.stringify(err)}`); 277 HiLog.info(TAG, `get file info failed with error message: ${JSON.stringify(err)}`); 278 return -1; 279 } finally { 280 if (inFile) { 281 fs.closeSync(inFile); 282 } 283 } 284} 285 286function getDLPInfo() { 287 return new Promise<DLPInfo>(async (resolve, reject) => { 288 let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT; 289 try { 290 bundleManager.getBundleInfoForSelf(bundleFlags, (err, data) => { 291 if (err) { 292 HiLog.error(TAG, `getBundleInfoForSelf failed. Cause: ${JSON.stringify(err)}`); 293 reject({name: '', versionCode: ''}); 294 } else { 295 resolve({name: data.name, versionCode: data.versionCode.toString()}); 296 } 297 }); 298 } catch (err) { 299 HiLog.error(TAG, `getBundleInfoForSelf failed. Cause: ${JSON.stringify(err)}`); 300 reject({name: '', versionCode: ''}); 301 } 302 }) 303} 304 305function sendDlpManagerAccountLogin(errorCode: number) { 306 let event: hiSysEvent.SysEventInfo = { 307 domain: 'DLP_UE', 308 name: 'DLP_MANAGER_ACCOUNT_LOGIN', 309 eventType: hiSysEvent?.EventType?.BEHAVIOR, 310 params: { 311 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 312 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 313 'ACCOUNT_TYPE': AppStorage.get('hiAccountType') ?? '', 314 'ACCOUNT_STATUS': AppStorage.get('hiAccountStatus') ?? -1, 315 'LOGIN_FAIL_CODE': errorCode ?? -1, 316 'PKG_NAME': AppStorage.get('hiPkgName') ?? '', 317 } as Record<string, number> 318 }; 319 320 try { 321 hiSysEvent.write(event); 322 } catch (err) { 323 HiLog.error(TAG, `sendDlpManagerAccountLogin failed`); 324 } 325} 326 327function sendDlpManagerFileConfiguration() { 328 let event: hiSysEvent.SysEventInfo = { 329 domain: 'DLP_UE', 330 name: 'DLP_MANAGER_FILE_CONFIGURATION', 331 eventType: hiSysEvent?.EventType?.BEHAVIOR, 332 params: { 333 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 334 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 335 'OPERATION': AppStorage.get('hiOperation') ?? '', 336 'READ_SCOPE': AppStorage.get('hiReadScope') ?? '', 337 'WRITE_SCOPE': AppStorage.get('hiWriteScope') ?? '', 338 'ADVANCED_SETTINGS': AppStorage.get('hiAdvancedSettings') ?? false, 339 'STORE_PATH': AppStorage.get('hiStorePath') ?? false, 340 'ACCOUNT_VERIFY_SUCC': AppStorage.get('hiAccountVerifySucc') ?? -1, 341 'ACCOUNT_VERIFY_FAIL': AppStorage.get('hiAccountVerifyFail') ?? -1, 342 'VALID_DATE': AppStorage.get('hiValidDate') ?? false, 343 } as Record<string, number> 344 }; 345 346 try { 347 hiSysEvent.write(event); 348 } catch (err) { 349 HiLog.error(TAG, `sendDlpManagerFileConfiguration failed`); 350 } 351} 352 353function sendDlpFileCreateProperties(accountType: number) { 354 let event: hiSysEvent.SysEventInfo = { 355 domain: 'DLP_UE', 356 name: 'DLP_FILE_CREATE_EVENT', 357 eventType: hiSysEvent?.EventType?.BEHAVIOR, 358 params: { 359 'ACCOUNT_TYPE': accountType, 360 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 361 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 362 'CODE': AppStorage.get('hiCode') ?? -1, 363 'FILE_SIZE': AppStorage.get('hiFileSize') ?? -1, 364 'FILE_TYPE': AppStorage.get('hiFileType') ?? '', 365 'POLICY_SIZE_ENC': AppStorage.get('hiPolicySizeEnc') ?? -1, 366 'PKG_NAME': AppStorage.get('hiPkgName') ?? '', 367 } as Record<string, number> 368 }; 369 370 try { 371 hiSysEvent.write(event); 372 } catch (err) { 373 HiLog.error(TAG, `sendDlpFileCreateProperties failed`); 374 } 375} 376 377function sendDlpFileOpenProperties() { 378 let event: hiSysEvent.SysEventInfo = { 379 domain: 'DLP_UE', 380 name: 'DLP_FILE_OPEN_EVENT', 381 eventType: hiSysEvent?.EventType?.BEHAVIOR, 382 params: { 383 'PNAMEID': AppStorage.get('hiPNameId') ?? '', 384 'PVERSIONID': AppStorage.get('hiPVersionId') ?? '', 385 'CODE': AppStorage.get('hiCode') ?? -1, 386 'SANDBOX_PKGNAME': AppStorage.get('hiSandboxPkgName') ?? '', 387 'SANDBOX_INDEX': AppStorage.get('hiSandboxIndex') ?? -1, 388 'ACCOUNT_TYPE': AppStorage.get('hiAccountType') ?? '', 389 'FILE_SIZE': AppStorage.get('hiFileSize') ?? -1, 390 'POLICY_SIZE_ENC': AppStorage.get('hiPolicySizeEnc') ?? -1, 391 } as Record<string, number> 392 }; 393 394 try { 395 hiSysEvent.write(event); 396 } catch (err) { 397 HiLog.error(TAG, `sendDlpFileOpenProperties failed`); 398 } 399} 400 401function isValidPath(path: string): Boolean { 402 if (path.indexOf('/./') !== -1 || path.indexOf('/../') !== -1) { 403 return false; 404 } 405 return true; 406} 407 408function getAccountType( 409 context: common.ServiceExtensionContext | common.UIExtensionContext, fd: number): Promise<number> { 410 return new Promise(async (resolve, reject) => { 411 let z = new ArrayBuffer(HEAD_LENGTH_IN_BYTE); 412 let option: ChangeOption = { offset: 0, length: HEAD_LENGTH_IN_BYTE }; 413 let num = fs.readSync(fd, z, option); 414 let buf = new Uint32Array(z, 0, HEAD_LENGTH_IN_U32); 415 if (buf && buf[0] === Constants.DLP_ZIP_MAGIC) { 416 let random = String(Math.random()).substring(Constants.RAND_START, Constants.RAND_END); 417 let filePath = context.filesDir + '/saveAs' + random; 418 let dirPath = context.filesDir + '/saveAsUnzip' + random; 419 let fileName = dirPath + '/dlp_cert'; 420 let ff: fs.File | undefined; 421 try { 422 fs.readSync(fd, z, option); 423 ff = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 424 await fs.copyFile(fd, ff.fd); 425 await fs.mkdir(dirPath); 426 await zlib.decompressFile(filePath, dirPath); 427 let dlpInfo = fs.readTextSync(fileName); 428 let infoArray = dlpInfo.split('accountType'); 429 let type = infoArray[1].slice(Constants.TYPE_START, Constants.TYPE_END); 430 GlobalContext.store('accountType', Number(type)); 431 resolve(Number(type)); 432 } catch (err) { 433 HiLog.error(TAG, `decompressFile: ${JSON.stringify(err)}`); 434 reject(); 435 } finally { 436 closeFile(ff); 437 deleteFile(filePath); 438 removeDir(dirPath); 439 } 440 } else { 441 let cert = new ArrayBuffer(buf[CERT_SIZE]); 442 option = { offset: buf[CERT_OFFSET], length: buf[CERT_SIZE] }; 443 num = fs.readSync(fd, cert, option); 444 try { 445 let textDecoder: util.TextDecoder = util.TextDecoder.create('utf-8'); 446 let fdString: string = textDecoder.decodeWithStream(new Uint8Array(cert), { stream: false }); 447 let infoArray = fdString.split('accountType'); 448 let type = infoArray[1].slice(Constants.TYPE_START, Constants.TYPE_END); 449 GlobalContext.store('accountType', Number(type)); 450 resolve(Number(type)); 451 } catch (err) { 452 HiLog.error(TAG, `getStringFromFd error: ${JSON.stringify(err)}`); 453 reject(); 454 } 455 } 456 }) 457} 458 459function closeFile(file: fs.File | undefined) { 460 try { 461 if (file) { 462 fs.closeSync(file); 463 } 464 } catch (err) { 465 HiLog.error(TAG, `closeSync: ${JSON.stringify(err)}`); 466 } 467} 468 469function deleteFile(file: string) { 470 try { 471 let res = fs.accessSync(file); 472 if (res) { 473 fs.unlinkSync(file); 474 } 475 } catch (err) { 476 HiLog.error(TAG, `deleteFile: ${JSON.stringify(err)}`); 477 } 478} 479 480function removeDir(file: string) { 481 try { 482 let res = fs.accessSync(file); 483 if (res) { 484 fs.rmdirSync(file); 485 } 486 } catch (err) { 487 HiLog.error(TAG, `rmdirSync: ${JSON.stringify(err)}`); 488 } 489} 490 491function checkNetworkStatus(): Promise<void> { 492 return new Promise((resolve, reject) => { 493 let netHandle = connection.getDefaultNetSync(); 494 connection.getNetCapabilities(netHandle, (error: BusinessError, data: connection.NetCapabilities) => { 495 if (error) { 496 HiLog.error(TAG, `checkNetworkStatus failed: ${JSON.stringify(error)}`); 497 reject(); 498 return; 499 }; 500 HiLog.info(TAG, `network Succeeded to get data: ${JSON.stringify(data)}`); 501 const result = [connection.NetCap.NET_CAPABILITY_INTERNET, connection.NetCap.NET_CAPABILITY_VALIDATED] 502 .every(element => data.networkCap?.includes(element)); 503 if (result) { 504 resolve(); 505 return; 506 } 507 reject(); 508 }) 509 }) 510} 511 512export { 513 AuthAccount, 514 PermissionType, 515 getOsAccountInfo, 516 checkDomainAccountInfo, 517 getUserId, 518 getAuthPerm, 519 terminateSelfWithResult, 520 judgeIsSandBox, 521 getFileFd, 522 getFileUriByPath, 523 removeDuplicate, 524 calculate, 525 toggleShow, 526 directionStatus, 527 getAppId, 528 getTime, 529 getFileSizeByUri, 530 getDLPInfo, 531 sendDlpManagerAccountLogin, 532 sendDlpManagerFileConfiguration, 533 sendDlpFileCreateProperties, 534 sendDlpFileOpenProperties, 535 DLPInfo, 536 isValidPath, 537 defaultDlpFile, 538 getAccountType, 539 checkNetworkStatus 540}; 541