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'; 21 22export const scanProjectConfig: { 23 mPropertyObfuscation?: boolean, 24 mKeepStringProperty?: boolean, 25 mExportObfuscation?: boolean, 26 mkeepFilesAndDependencies?: Set<string>, 27 isHarCompiled?: boolean 28} = {}; 29 30/** 31 * if rename property is not open, api read and extract can be skipped 32 * 33 * init plugin, read api info of openHarmony sdk and generate file of reserved name, property and string. 34 * @param sdkDir absolute path like D:\\HuaweiApp\\ohsdk 35 * @param outputDir 36 */ 37export function initPlugin(sdkDir: string, outputDir: string): void { 38 // create sdk api file if not exist 39 const ohSdkPath: string = path.resolve(sdkDir); 40 if (!ohSdkPath) { 41 console.error('SDK path is not found.'); 42 } 43 44 const apiVersions: string[] = ['']; 45 46 apiVersions.forEach((versionString) => { 47 ApiExtractor.parseOhSdk(ohSdkPath, versionString, true, outputDir); 48 }); 49} 50 51/** 52 * need read api info or not 53 * @param customProfiles 54 */ 55export function needReadApiInfo(customProfiles: IOptions): boolean { 56 return isEnabledPropertyObfuscation(customProfiles) || customProfiles.mExportObfuscation; 57} 58 59export function isEnabledPropertyObfuscation(customProfiles: IOptions): boolean { 60 return (customProfiles.mNameObfuscation && 61 customProfiles.mNameObfuscation.mEnable && 62 customProfiles.mNameObfuscation.mRenameProperties); 63} 64 65function initScanProjectConfig(customProfiles: IOptions, isHarCompiled?: boolean) { 66 scanProjectConfig.mPropertyObfuscation = customProfiles.mNameObfuscation?.mRenameProperties; 67 scanProjectConfig.mKeepStringProperty = customProfiles.mNameObfuscation?.mKeepStringProperty; 68 scanProjectConfig.mExportObfuscation = customProfiles.mExportObfuscation; 69 scanProjectConfig.mkeepFilesAndDependencies = customProfiles.mKeepFileSourceCode?.mkeepFilesAndDependencies; 70 scanProjectConfig.isHarCompiled = isHarCompiled; 71} 72 73export interface ReseverdSetForArkguard { 74 structPropertySet: Set<string> | undefined; 75 stringPropertySet: Set<string> | undefined; 76 exportNameAndPropSet: Set<string> | undefined; 77 exportNameSet: Set<string> | undefined; 78 enumPropertySet: Set<string> | undefined; 79} 80 81/** 82 * read project reserved properties by collected paths 83 * @param filesForCompilation set collection of files 84 * @param customProfiles 85 */ 86export function readProjectPropertiesByCollectedPaths(filesForCompilation: Set<string>, 87 customProfiles: IOptions, isHarCompiled: boolean): ReseverdSetForArkguard { 88 const ApiType = ApiExtractor.ApiType; 89 let scanningCommonType = undefined; 90 let scanningLibsType = undefined; 91 if (needReadApiInfo(customProfiles)) { 92 scanningCommonType = ApiType.PROJECT; 93 scanningLibsType = ApiType.PROJECT_DEPENDS; 94 } else { 95 scanningCommonType = ApiType.CONSTRUCTOR_PROPERTY; 96 scanningLibsType = ApiType.CONSTRUCTOR_PROPERTY; 97 } 98 // The purpose of collecting constructor properties is to avoid generating the same name as the constructor property when obfuscating identifier names. 99 ApiExtractor.mConstructorPropertySet = new Set(); 100 101 initScanProjectConfig(customProfiles, isHarCompiled); 102 103 stringPropsSet.clear(); 104 105 const exportWhiteList = ApiExtractor.parseFileByPaths(filesForCompilation, scanningCommonType); 106 const exportNamesAndProperties: Set<string> | undefined = exportWhiteList.reservedExportPropertyAndName; 107 const exportNames: Set<string> | undefined = exportWhiteList.reservedExportNames; 108 109 // if -enable-property-obfuscation, collect structPropsSet, exportNamesAndProperties and 110 // stringPropsSet(if -enable-string-property-obufscation is not enabled) as whitelists. 111 let exportNameAndPropSet: Set<string>; 112 let structPropertySet: Set<string>; 113 let stringPropertySet: Set<string>; 114 let enumPropertySet: Set<string>; 115 if (isEnabledPropertyObfuscation(customProfiles)) { 116 exportNameAndPropSet = new Set(exportNamesAndProperties); 117 structPropertySet = new Set(structPropsSet); 118 enumPropertySet = new Set(enumPropsSet); 119 if (scanProjectConfig.mKeepStringProperty) { 120 stringPropertySet = new Set(stringPropsSet); 121 } 122 } 123 structPropsSet.clear(); 124 stringPropsSet.clear(); 125 enumPropsSet.clear(); 126 127 let exportNameSet: Set<string>; 128 if (scanProjectConfig.mExportObfuscation) { 129 exportNameSet = new Set(exportNames); 130 } 131 132 return { 133 structPropertySet: structPropertySet, 134 stringPropertySet: stringPropertySet, 135 exportNameAndPropSet: exportNameAndPropSet, 136 exportNameSet: exportNameSet, 137 enumPropertySet: enumPropertySet, 138 }; 139} 140