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 path from 'path'; 17import {ApiExtractor} from './ApiExtractor'; 18import {ListUtil} from '../utils/ListUtil'; 19import type {IOptions} from '../configs/IOptions'; 20import { stringPropsSet, structPropsSet, enumPropsSet } from '../utils/OhsUtil'; 21import type { MergedConfig } from '../ArkObfuscator'; 22 23// The interface of settings for collect while lists 24export interface ScanProjectConfig { 25 mPropertyObfuscation?: boolean, 26 mKeepStringProperty?: boolean, 27 mExportObfuscation?: boolean, 28 mkeepFilesAndDependencies?: Set<string>, 29 isHarCompiled?: boolean, 30 mStripSystemApiArgs?: boolean, 31 mEnableAtKeep: boolean 32} 33 34// Settings for collect white lists. 35export let scanProjectConfig: ScanProjectConfig = { 36 mEnableAtKeep: false 37}; 38 39/** 40 * if rename property is not open, api read and extract can be skipped 41 * 42 * init plugin, read api info of openHarmony sdk and generate file of reserved name, property and string. 43 * @param sdkDir absolute path like D:\\HuaweiApp\\ohsdk 44 * @param outputDir 45 */ 46export function initPlugin(sdkDir: string, outputDir: string): void { 47 // create sdk api file if not exist 48 const ohSdkPath: string = path.resolve(sdkDir); 49 if (!ohSdkPath) { 50 console.error('SDK path is not found.'); 51 } 52 53 const apiVersions: string[] = ['']; 54 55 apiVersions.forEach((versionString) => { 56 ApiExtractor.parseOhSdk(ohSdkPath, versionString, true, outputDir); 57 }); 58} 59 60/** 61 * need read api info or not 62 * @param customProfiles 63 */ 64export function needReadApiInfo(customProfiles: IOptions): boolean { 65 return isEnabledPropertyObfuscation(customProfiles) || customProfiles.mExportObfuscation; 66} 67 68export function isEnabledPropertyObfuscation(customProfiles: IOptions): boolean { 69 return (customProfiles.mNameObfuscation && 70 customProfiles.mNameObfuscation.mEnable && 71 customProfiles.mNameObfuscation.mRenameProperties); 72} 73 74function initScanProjectConfig(customProfiles: IOptions, isHarCompiled?: boolean): void { 75 scanProjectConfig.mPropertyObfuscation = customProfiles.mNameObfuscation?.mRenameProperties; 76 scanProjectConfig.mKeepStringProperty = customProfiles.mNameObfuscation?.mKeepStringProperty; 77 scanProjectConfig.mExportObfuscation = customProfiles.mExportObfuscation; 78 scanProjectConfig.mkeepFilesAndDependencies = customProfiles.mKeepFileSourceCode?.mkeepFilesAndDependencies; 79 scanProjectConfig.isHarCompiled = isHarCompiled; 80 scanProjectConfig.mEnableAtKeep = customProfiles.mNameObfuscation?.mEnableAtKeep; 81} 82 83/** 84 * Initialize scanProjectConfig by MergeConfig 85 * @param mergedConfig 86 */ 87export function initScanProjectConfigByMergeConfig(config: MergedConfig): void { 88 scanProjectConfig.mStripSystemApiArgs = config.options.stripSystemApiArgs; 89} 90 91/** 92 * Reset scanProjectConfig 93 */ 94export function resetScanProjectConfig(): void { 95 scanProjectConfig.mStripSystemApiArgs = undefined; 96} 97 98export interface ReseverdSetForArkguard { 99 structPropertySet: Set<string> | undefined; 100 stringPropertySet: Set<string> | undefined; 101 exportNameAndPropSet: Set<string> | undefined; 102 exportNameSet: Set<string> | undefined; 103 enumPropertySet: Set<string> | undefined; 104} 105 106/** 107 * read project reserved properties by collected paths 108 * @param filesForCompilation set collection of files 109 * @param customProfiles 110 */ 111export function readProjectPropertiesByCollectedPaths(filesForCompilation: Set<string>, 112 customProfiles: IOptions, isHarCompiled: boolean): ReseverdSetForArkguard { 113 const apiType = ApiExtractor.ApiType; 114 let scanningCommonType = undefined; 115 if (needReadApiInfo(customProfiles)) { 116 scanningCommonType = apiType.PROJECT; 117 } else { 118 scanningCommonType = apiType.CONSTRUCTOR_PROPERTY; 119 } 120 121 initScanProjectConfig(customProfiles, isHarCompiled); 122 123 stringPropsSet.clear(); 124 125 const exportWhiteList = ApiExtractor.parseFileByPaths(filesForCompilation, scanningCommonType); 126 const exportNamesAndProperties: Set<string> | undefined = exportWhiteList.reservedExportPropertyAndName; 127 const exportNames: Set<string> | undefined = exportWhiteList.reservedExportNames; 128 129 // if -enable-property-obfuscation, collect structPropsSet, exportNamesAndProperties and 130 // stringPropsSet(if -enable-string-property-obufscation is not enabled) as whitelists. 131 let exportNameAndPropSet: Set<string>; 132 let structPropertySet: Set<string>; 133 let stringPropertySet: Set<string>; 134 let enumPropertySet: Set<string>; 135 if (isEnabledPropertyObfuscation(customProfiles)) { 136 exportNameAndPropSet = new Set(exportNamesAndProperties); 137 structPropertySet = new Set(structPropsSet); 138 enumPropertySet = new Set(enumPropsSet); 139 if (scanProjectConfig.mKeepStringProperty) { 140 stringPropertySet = new Set(stringPropsSet); 141 } 142 } 143 structPropsSet.clear(); 144 stringPropsSet.clear(); 145 enumPropsSet.clear(); 146 147 let exportNameSet: Set<string>; 148 if (scanProjectConfig.mExportObfuscation) { 149 exportNameSet = new Set(exportNames); 150 } 151 152 // scanProjectConfig needs to be cleared to prevent affecting incremental compilation 153 scanProjectConfig = { 154 mEnableAtKeep: false 155 }; 156 157 return { 158 structPropertySet: structPropertySet, 159 stringPropertySet: stringPropertySet, 160 exportNameAndPropSet: exportNameAndPropSet, 161 exportNameSet: exportNameSet, 162 enumPropertySet: enumPropertySet, 163 }; 164} 165