• 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 fs from 'fs';
17import path from 'path';
18import type * as ts from 'typescript';
19import {
20  ApiExtractor,
21  clearGlobalCaches
22} from 'arkguard';
23import type {
24  ArkObfuscator,
25} from 'arkguard';
26
27import { toUnixPath } from '../../../utils';
28import { allSourceFilePaths, localPackageSet } from '../../../ets_checker';
29import { isCurrentProjectFiles } from '../utils';
30import { sourceFileBelongProject } from '../module/module_source_file';
31
32export {
33  collectResevedFileNameInIDEConfig, // For running unit test.
34  enableObfuscatedFilePathConfig,
35  enableObfuscateFileName,
36  generateConsumerObConfigFile,
37  getRelativeSourcePath,
38  handleObfuscatedFilePath,
39  handleUniversalPathInObf,
40  mangleFilePath,
41  MergedConfig,
42  nameCacheMap,
43  ObConfigResolver,
44  readNameCache,
45  writeObfuscationNameCache
46} from 'arkguard';
47
48export function resetObfuscation(): void {
49  clearGlobalCaches();
50  sourceFileBelongProject.clear();
51  ApiExtractor.mPropertySet?.clear();
52  ApiExtractor.mSystemExportSet?.clear();
53  localPackageSet?.clear();
54}
55
56// Collect all keep files. If the path configured by the developer is a folder, all files in the compilation will be used to match this folder.
57function collectAllKeepFiles(startPaths: string[], excludePathSet: Set<string>): Set<string> {
58  const allKeepFiles: Set<string> = new Set();
59  const keepFolders: string[] = [];
60  startPaths.forEach(filePath => {
61    if (excludePathSet.has(filePath)) {
62      return;
63    }
64    if (fs.statSync(filePath).isDirectory()) {
65      keepFolders.push(filePath);
66    } else {
67      allKeepFiles.add(filePath);
68    }
69  });
70  if (keepFolders.length === 0) {
71    return allKeepFiles;
72  }
73
74  allSourceFilePaths.forEach(filePath => {
75    if (keepFolders.some(folderPath => filePath.startsWith(folderPath)) && !excludePathSet.has(filePath)) {
76      allKeepFiles.add(filePath);
77    }
78  });
79  return allKeepFiles;
80}
81
82// Collect all keep files and then collect their dependency files.
83export function handleKeepFilesAndGetDependencies(resolvedModulesCache: Map<string, ts.ResolvedModuleFull[]>,
84  mergedObConfig: MergedConfig, projectRootPath: string, arkObfuscator: ArkObfuscator, projectConfig: Object): Set<string> {
85  if (mergedObConfig === undefined || mergedObConfig.keepSourceOfPaths.length === 0) {
86    return new Set<string>();
87  }
88  const keepPaths = mergedObConfig.keepSourceOfPaths;
89  const excludePaths = mergedObConfig.excludePathSet;
90  let allKeepFiles: Set<string> = collectAllKeepFiles(keepPaths, excludePaths);
91  arkObfuscator.setKeepSourceOfPaths(allKeepFiles);
92  const keepFilesAndDependencies: Set<string> = getFileNamesForScanningWhitelist(resolvedModulesCache, mergedObConfig,
93    allKeepFiles, projectRootPath, projectConfig);
94  return keepFilesAndDependencies;
95}
96
97/**
98 * Use tsc's dependency collection to collect the dependency files of the keep files.
99 * Risk: The files resolved by typescript are different from the files resolved by rollup. For example, the two entry files have different priorities.
100 * Tsc looks for files in the types field in oh-packagek.json5 first, and rollup looks for files in the main field.
101 */
102function getFileNamesForScanningWhitelist(
103  resolvedModulesCache: Map<string, ts.ResolvedModuleFull[]>,
104  mergedObConfig: MergedConfig,
105  allKeepFiles: Set<string>,
106  projectRootPath: string,
107  projectConfig: Object): Set<string> {
108  const keepFilesAndDependencies: Set<string> = new Set<string>();
109  if (!mergedObConfig.options.enableExportObfuscation) {
110    return keepFilesAndDependencies;
111  }
112  let stack: string[] = Array.from(allKeepFiles);
113  projectRootPath = toUnixPath(projectRootPath);
114  while (stack.length > 0) {
115    const filePath = stack.pop();
116    if (keepFilesAndDependencies.has(filePath)) {
117      continue;
118    }
119
120    keepFilesAndDependencies.add(filePath);
121    const resolvedModules = resolvedModulesCache.get(path.resolve(filePath));
122    if (!resolvedModules) {
123      continue;
124    }
125
126    for (const resolvedModule of resolvedModules) {
127      // For `import moduleName form 'xx.so'`, when the xx.so cannot be resolved, resolvedModules is [null]
128      if (!resolvedModule) {
129        continue;
130      }
131      let tempPath = toUnixPath(resolvedModule.resolvedFileName);
132      // resolvedModule can record system API declaration files and ignore them.
133      if (isCurrentProjectFiles(tempPath, projectConfig)) {
134        stack.push(tempPath);
135      }
136    }
137  }
138  return keepFilesAndDependencies;
139}