• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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