• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 { BusinessError } from '@ohos.base';
17import Want from '@ohos.app.ability.Want';
18import fileUri from '@ohos.file.fileuri';
19import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
20import fs from '@ohos.file.fs';
21import dlpPermission from '@ohos.dlpPermission';
22import IdlDlpRpcServiceStub from './data/IIdlDlpRpcServiceTs/id_dlpRpc_service_stub';
23import {
24  closeDlpFileCallback,
25  sandBoxLinkFileCallback,
26  fileOpenHistoryCallback,
27  linkSetCallback,
28  genDlpFileCallback,
29  openDlpFileCallback,
30  recoverDlpFileCallback,
31  replaceDlpLinkFileCallback,
32  resumeFuseLinkCallback,
33  stopFuseLinkCallback
34} from './data/IIdlDlpRpcServiceTs/i_id_dlpRpc_service';
35import IDLDLPProperty from '../common/dlpClass';
36import { IAuthUser } from '../common/dlpClass';
37import GlobalContext from '../common/GlobalContext';
38import Constants from '../common/constant';
39import { HiLog } from '../common/HiLog';
40import FileUtil from '../common/external/FileUtil';
41
42const TAG = 'DlpRpcServiceStub';
43
44class DlpRpcServiceStub extends IdlDlpRpcServiceStub {
45  private dlpFileMap: Map<string, dlpPermission.DLPFile | null> = new Map<string, dlpPermission.DLPFile | null>();
46  private inFile: fs.File | undefined = undefined;
47  private outFile: fs.File | undefined = undefined;
48
49  constructor(des: string) {
50    super(des);
51  }
52
53  getOpeningFile(inputUri: string) : dlpPermission.DLPFile | null {
54    let sandbox2linkFile: Map<string, (number | string | dlpPermission.DLPFile)[][]> = GlobalContext.load('sandbox2linkFile') as Map<string, (number | string | dlpPermission.DLPFile)[][]>;
55    if (sandbox2linkFile !== undefined) {
56      for (let key of Array.from<(number | string | dlpPermission.DLPFile)[][]>(sandbox2linkFile.values())) {
57        for (let j of key) {
58          if (j[4] === inputUri) {
59            let dlpFile: dlpPermission.DLPFile = j[0] as dlpPermission.DLPFile;
60            return dlpFile;
61          }
62        }
63      }
64    }
65
66    if (this.dlpFileMap.has(inputUri)) {
67      let dlpFile: dlpPermission.DLPFile = this.dlpFileMap.get(inputUri) as dlpPermission.DLPFile;
68      return dlpFile;
69    }
70    return null;
71  }
72
73  async genDlpFile(inputUri: string, outputUri: string, dlp: IDLDLPProperty, callback: genDlpFileCallback
74  ): Promise<void> {
75    HiLog.info(TAG, `genDlpFile in service`);
76    let result: Record<string, number>;
77    try {
78      result = await this.genDlpFileFd(inputUri, outputUri);
79    } catch (error) {
80      callback(error);
81      return;
82    }
83    let dlpP: dlpPermission.DLPProperty = {
84      'ownerAccount' : dlp.ownerAccount,
85      'ownerAccountID' : dlp.ownerAccountID,
86      'ownerAccountType' : dlp.ownerAccountType,
87      'authUserList' : dlp.authUserList,
88      'contactAccount' : dlp.contactAccount,
89      'offlineAccess' : dlp.offlineAccess,
90      'everyoneAccessList' : dlp.everyoneAccessList,
91      'expireTime': dlp.expireTime
92    }
93    try {
94      let dlpFile = await dlpPermission.generateDLPFile(result.inFileFd, result.outFileFd, dlpP);
95      if (!this.dlpFileMap.has(outputUri)) {
96        this.dlpFileMap.set(outputUri, dlpFile);
97        AppStorage.setOrCreate('dlpFileMap', this.dlpFileMap);
98      } else {
99        let rawDlpFile = this.dlpFileMap.get(outputUri) ?? null;
100        if (rawDlpFile !== null) {
101          try {
102            await rawDlpFile.closeDLPFile();
103          } catch (err) {
104            HiLog.error(TAG, `closeDlpFile file: ${JSON.stringify(err)}`);
105          }
106        }
107        this.dlpFileMap.delete(outputUri);
108        this.dlpFileMap.set(outputUri, dlpFile);
109        AppStorage.setOrCreate('dlpFileMap', this.dlpFileMap);
110      }
111      callback(0);
112    } catch (err) {
113      HiLog.error(TAG, `genDlpFile file: ${JSON.stringify(err)}`);
114      await this.closeFile();
115      callback((err as BusinessError).code);
116    }
117  }
118
119  async closeFile(): Promise<void> {
120    FileUtil.closeFileSync(this.inFile);
121    FileUtil.closeFileSync(this.outFile);
122  }
123
124  async genDlpFileFd(inputUri: string, outputUri: string): Promise<Record<string, number>> {
125    return new Promise(async (resolve, reject) => {
126      let inFileFd: number = -1;
127      let outFileFd: number = -1;
128      try {
129        this.inFile = await fs.open(inputUri, fs.OpenMode.READ_WRITE);
130        inFileFd = this.inFile.fd;
131      } catch (error) {
132        HiLog.error(TAG, `open: ${inputUri}, failed: ${JSON.stringify(error)}`);
133        reject((error as BusinessError).code);
134        return;
135      }
136      let uriInfo: fileUri.FileUri = new fileUri.FileUri('');
137      try {
138        uriInfo = new fileUri.FileUri(outputUri);
139      } catch (err) {
140        HiLog.error(TAG, `fileUri fail: ${JSON.stringify(err)}`);
141      }
142      try {
143        this.outFile = await fs.open(outputUri, fs.OpenMode.READ_WRITE);
144        outFileFd = this.outFile.fd;
145      } catch (error) {
146        FileUtil.closeFileSync(this.inFile);
147        FileUtil.unlinkSync(uriInfo.path);
148        reject((error as BusinessError).code);
149        return;
150      }
151      let result = {
152        'inFileFd': inFileFd,
153        'outFileFd': outFileFd
154      } as Record<string, number>;
155      resolve(result);
156    })
157  }
158
159  async openDlpFile(srcUri: string, callerAppId: string, callback: openDlpFileCallback): Promise<void> {
160    HiLog.info(TAG, `openDlpFile start: ${srcUri}`);
161    let inFile = await fs.open(srcUri, fs.OpenMode.READ_WRITE);
162    let dlpFile: dlpPermission.DLPFile;
163    let authUserListNew: IAuthUser[] = [];
164    try {
165      dlpFile = await dlpPermission.openDLPFile(inFile.fd, callerAppId);
166      dlpFile.dlpProperty.authUserList?.forEach(item => {
167        authUserListNew.push(
168          new IAuthUser(
169            item.authAccount,
170            item.authAccountType,
171            item.dlpFileAccess,
172            item.permExpiryTime
173          ))
174      })
175      let _dlp = new IDLDLPProperty(
176        dlpFile.dlpProperty.ownerAccount,
177        dlpFile.dlpProperty.ownerAccountID,
178        dlpFile.dlpProperty.ownerAccountType,
179        authUserListNew,
180        dlpFile.dlpProperty.contactAccount,
181        dlpFile.dlpProperty.offlineAccess,
182        dlpFile.dlpProperty.everyoneAccessList ?? [],
183        dlpFile.dlpProperty.expireTime ?? 0,
184      );
185      callback(0, _dlp, '');
186      if (!this.dlpFileMap.has(srcUri)) {
187        this.dlpFileMap.set(srcUri, dlpFile);
188        AppStorage.setOrCreate('dlpFileMap', this.dlpFileMap);
189      } else {
190        HiLog.info(TAG, `map is overwrite`);
191        this.dlpFileMap.delete(srcUri);
192        this.dlpFileMap.set(srcUri, dlpFile);
193        AppStorage.setOrCreate('dlpFileMap', this.dlpFileMap);
194      }
195    } catch (err) {
196      let _dlp = new IDLDLPProperty('', '', 0, [], '', true, [], 0);
197      callback((err as BusinessError).code, _dlp, (err as BusinessError).message);
198    } finally {
199      FileUtil.closeFileSync(inFile);
200    }
201  }
202
203  async stopFuseLink(uri: string, callback: stopFuseLinkCallback): Promise<void> {
204    HiLog.info(TAG, `stopFuseLink start: ${uri}`);
205    let dlpFile: dlpPermission.DLPFile | null = this.getOpeningFile(uri);
206    if (dlpFile !== null) {
207      await dlpFile.stopFuseLink();
208    } else {
209      HiLog.error(TAG, `stopFuseLink not find: ${uri}`);
210      callback(-1);
211    }
212  }
213
214  async resumeFuseLink(uri: string, callback: resumeFuseLinkCallback): Promise<void> {
215    HiLog.info(TAG, `resumeFuseLink start`);
216    let dlpFile: dlpPermission.DLPFile | null = this.getOpeningFile(uri);
217    if (dlpFile !== null) {
218      await dlpFile.resumeFuseLink();
219    } else {
220      HiLog.error(TAG, `resumeFuseLink not find: ${uri}`);
221      callback(-1);
222    }
223  }
224
225  async replaceDlpLinkFile(srcUri: string, linkFileName: string, callback: replaceDlpLinkFileCallback): Promise<void> {
226    GlobalContext.load('sandbox2linkFile');
227    if (this.dlpFileMap.has(srcUri)) {
228      let dlpFile: dlpPermission.DLPFile = this.dlpFileMap.get(srcUri) as dlpPermission.DLPFile;
229      let sandbox2linkFile: Map<string, (number | string | dlpPermission.DLPFile)[][]> = GlobalContext.load('sandbox2linkFile') as Map<string, (number | string | dlpPermission.DLPFile)[][]>;
230      for (let key of Array.from<(number | string | dlpPermission.DLPFile)[][]>(sandbox2linkFile.values())) {
231        for (let j of key) {
232          if (j[1] === linkFileName) {
233            j[0] = dlpFile;
234          }
235        }
236      }
237      await dlpFile.replaceDLPLinkFile(linkFileName);
238    } else {
239      HiLog.error(TAG, `replaceDLPLinkFile not find: ${srcUri}`);
240      callback(-1);
241    }
242  }
243
244  async recoverDlpFile(srcUri: string, pathUri: string, callback: recoverDlpFileCallback): Promise<void> {
245    let dlpFile: dlpPermission.DLPFile | null = this.getOpeningFile(srcUri);
246    if (dlpFile !== null) {
247      let inFile: fs.File | undefined;
248      try {
249        inFile = await fs.open(pathUri, fs.OpenMode.READ_WRITE);
250        await dlpFile.recoverDLPFile(inFile.fd);
251      } catch (err) {
252        HiLog.error(TAG, `recoverDlpFileInner4: ${JSON.stringify(err)}`);
253        callback((err as BusinessError).code);
254      } finally {
255        FileUtil.closeFileSync(inFile);
256      }
257    } else {
258      HiLog.error(TAG, `recoverDlpFile not find: ${srcUri}`);
259      callback(-1);
260    }
261  }
262
263  async closeDlpFile(srcUri: string, callback: closeDlpFileCallback): Promise<void> {
264    HiLog.info(TAG, `closeDlpFile start`);
265    let dlpFile: dlpPermission.DLPFile | null = this.getOpeningFile(srcUri);
266    if (dlpFile !== null) {
267      try {
268        await dlpFile.closeDLPFile();
269        if (this.dlpFileMap.has(srcUri)) {
270          this.dlpFileMap.delete(srcUri);
271          AppStorage.setOrCreate('dlpFileMap', this.dlpFileMap);
272        }
273        callback(0);
274      } catch (err) {
275        HiLog.error(TAG, `closeDlpFile file: ${JSON.stringify(err)}`);
276        callback((err as BusinessError).code);
277      }
278    }
279  }
280
281  async sandBoxLinkFile(linkFileName: string, callerToken: number, callback: sandBoxLinkFileCallback): Promise<void> {
282    let sandbox2linkFile: Map<string, (number | string | dlpPermission.DLPFile)[][]> = GlobalContext.load('sandbox2linkFile') as Map<string, (number | string | dlpPermission.DLPFile)[][]>;
283    for (let value of Array.from<(number | string | dlpPermission.DLPFile)[][]>(sandbox2linkFile.values())) {
284      for (let linkFile of value) {
285        let _dlp = new IDLDLPProperty('', '', 0, [], '', true, [], 0);
286        if (linkFile[Constants.FILE_OPEN_HISTORY_ONE] === linkFileName) {
287          let authUserListNew: IAuthUser[] = [];
288          if (callerToken !== linkFile[Constants.FILE_OPEN_HISTORY_THREE]) {
289            HiLog.error(TAG, `found file, but token invalid: ${linkFileName}`);
290            callback(-1, _dlp, '');
291          } else {
292            let linkFileInfo: Record<number, number | string | dlpPermission.DLPFile> =
293              linkFile[0] as Record<number, number | string | dlpPermission.DLPFile>;
294            linkFileInfo['dlpProperty'].authUserList.forEach((item: IAuthUser)=> {
295              authUserListNew.push(
296                new IAuthUser(
297                  item.authAccount,
298                  item.authAccountType,
299                  item.dlpFileAccess,
300                  item.permExpiryTime
301                ))
302            })
303            _dlp = new IDLDLPProperty(
304              linkFileInfo['dlpProperty'].ownerAccount,
305              linkFileInfo['dlpProperty'].ownerAccountID,
306              linkFileInfo['dlpProperty'].ownerAccountType,
307              authUserListNew,
308              linkFileInfo['dlpProperty'].contactAccount,
309              linkFileInfo['dlpProperty'].offlineAccess,
310              linkFileInfo['dlpProperty'].everyoneAccessList ?? [],
311              linkFileInfo['dlpProperty'].expireTime ?? 0
312            );
313            let fileUri = linkFile[4];
314            callback(0, _dlp, fileUri.toString());
315          }
316        } else {
317          HiLog.error(TAG, `request from sandbox, but can not find dlp file by linkFileName: ${linkFileName}`);
318          callback(-1, _dlp, '');
319        }
320      }
321    }
322  }
323
324  async fileOpenHistory(uri: string, callback: fileOpenHistoryCallback): Promise<void> {
325    HiLog.info(TAG, `fileOpenHistory start`);
326    if ((GlobalContext.load('fileOpenHistory') as Map<string, (number | string)[]>)?.has(uri)) {
327      callback(0);
328    } else {
329      callback(-1);
330    }
331  }
332
333  async linkSet(uri: string, callback: linkSetCallback): Promise<void> {
334    HiLog.info(TAG, `linkSet start`);
335    if ((GlobalContext.load('linkSet') as Map<string, (number | string)[]>)?.has(uri)) {
336      callback(0);
337    } else {
338      callback(-1);
339    }
340  }
341}
342
343export default class DlpFileProcessAbility extends ServiceExtensionAbility {
344  onCreate(want: Want) {
345    HiLog.info(TAG, `onCreate, want: ${want.abilityName}`);
346  }
347
348  onRequest(want: Want, startId: number) {
349    HiLog.info(TAG, `onRequest, want: ${want.abilityName}`);
350  }
351
352  onConnect(want: Want) {
353    HiLog.info(TAG, `service onConnect, want: ${want.abilityName}`);
354    return new DlpRpcServiceStub('dlpRpc service stub');
355  }
356
357  onDisconnect(want: Want): void {
358    HiLog.info(TAG, `onDisconnect, want: ${want.abilityName}`);
359  }
360
361  onDestroy(): void {
362    HiLog.info(TAG, `onDestroy`);
363  }
364}