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