diff --git a/arkguard/package.json b/arkguard/package.json index 3a1347a942d54395899dfc4843ba5004ecbf6982..b189cb9bcfbf61dd06585e5df6681f5d3a9bd8b1 100644 --- a/arkguard/package.json +++ b/arkguard/package.json @@ -1,6 +1,6 @@ { "name": "arkguard", - "version": "1.1.0", + "version": "1.1.1", "description": "An obfuscator tools for open harmony apps.", "bin": { "arkguard": "bin/secharmony" diff --git a/arkguard/scripts/grammarTestScript.js b/arkguard/scripts/grammarTestScript.js index de1e34825e52a9f5502bb8d103cb487cd55189ec..643af2330d51196dc18ec84b87b0c4f466ceb2df 100644 --- a/arkguard/scripts/grammarTestScript.js +++ b/arkguard/scripts/grammarTestScript.js @@ -69,7 +69,8 @@ function runTestsInDirectory(directoryPath) { failedFiles.push(filePath); } } - } else if (path.extname(filePath) === '.ts' || path.extname(filePath) === '.js') { + } else if ((path.extname(filePath) === '.ts' || path.extname(filePath) === '.js') && (!filePath.endsWith('.d.ets') && + !filePath.endsWith('.d.ts'))) { const isSuccess = runTest(filePath); if (isSuccess) { successCount++; diff --git a/arkguard/src/ArkObfuscator.ts b/arkguard/src/ArkObfuscator.ts index 9d8af3cfee537c8692879b07c1bd3429adea0821..ed4795d8c9e1021b93237a6de4ff02ae206afc36 100644 --- a/arkguard/src/ArkObfuscator.ts +++ b/arkguard/src/ArkObfuscator.ts @@ -56,13 +56,16 @@ import es6Info from './configs/preset/es6_reserved_properties.json'; export const renameIdentifierModule = require('./transformers/rename/RenameIdentifierTransformer'); export const renamePropertyModule = require('./transformers/rename/RenamePropertiesTransformer'); +export const renameFileNameModule = require('./transformers/rename/RenameFileNameTransformer'); export {getMapFromJson, readProjectProperties}; +export let orignalFilePathForSearching: string | undefined; type ObfuscationResultType = { content: string, sourceMap?: RawSourceMap, - nameCache?: { [k: string]: string } + nameCache?: { [k: string]: string }, + filePath?: string }; const JSON_TEXT_INDENT_LENGTH: number = 2; @@ -168,9 +171,13 @@ export class ArkObfuscator { */ private async obfuscateDir(dirName: string, dirPrefix: string): Promise { const currentDir: string = FileUtils.getPathWithoutPrefix(dirName, dirPrefix); - const newDir: string = path.join(this.mCustomProfiles.mOutputDir, currentDir); - if (!fs.existsSync(newDir)) { - fs.mkdirSync(newDir); + let newDir: string = this.mCustomProfiles.mOutputDir; + // there is no need to create directory because the directory names will be obfuscated. + if (!this.mCustomProfiles.mRenameFileName?.mEnable) { + newDir = path.join(this.mCustomProfiles.mOutputDir, currentDir); + if (!fs.existsSync(newDir)) { + fs.mkdirSync(newDir); + } } const fileNames: string[] = fs.readdirSync(dirName); @@ -214,8 +221,8 @@ export class ArkObfuscator { renamePropertyModule.historyMangledTable = getMapFromJson(propertyCache); } - private produceNameCache(namecache: { [k: string]: string }, sourceFile: string, outputDir: string): void { - const nameCachePath: string = path.join(outputDir, FileUtils.getFileName(sourceFile) + NAME_CACHE_SUFFIX); + private produceNameCache(namecache: { [k: string]: string }, resultPath: string): void { + const nameCachePath: string = resultPath + NAME_CACHE_SUFFIX; fs.writeFileSync(nameCachePath, JSON.stringify(namecache, null, JSON_TEXT_INDENT_LENGTH)); } @@ -266,10 +273,10 @@ export class ArkObfuscator { /** * A Printer to output obfuscated codes. */ - public createObfsPrinter(): Printer { + public createObfsPrinter(isDeclarationFile: boolean): Printer { // set print options let printerOptions: PrinterOptions = {}; - if (this.mCustomProfiles.mRemoveComments) { + if (this.mCustomProfiles.mRemoveComments && !isDeclarationFile) { printerOptions.removeComments = true; } @@ -279,7 +286,7 @@ export class ArkObfuscator { private isObfsIgnoreFile(fileName: string): boolean { let suffix: string = FileUtils.getFileExtension(fileName); - return (suffix !== 'js' && suffix !== 'ts') || fileName.endsWith('.d.ts'); + return (suffix !== 'js' && suffix !== 'ts' && suffix !== 'ets'); } /** @@ -295,18 +302,35 @@ export class ArkObfuscator { return; } + // Add the whitelist of file name obfuscation for ut. + if (this.mCustomProfiles.mRenameFileName?.mEnable) { + this.mCustomProfiles.mRenameFileName.mReservedFileNames.push(this.mConfigPath); + } let content: string = FileUtils.readFile(sourceFilePath); this.readNameCache(sourceFilePath, outputDir); const mixedInfo: ObfuscationResultType = await this.obfuscate(content, sourceFilePath); if (outputDir && mixedInfo) { - fs.writeFileSync(path.join(outputDir, FileUtils.getFileName(sourceFilePath)), mixedInfo.content); + // the writing file is for the ut. + const testCasesRootPath = path.join(__dirname, '../', 'test/grammar'); + let relativePath = ''; + let resultPath = ''; + if (this.mCustomProfiles.mRenameFileName?.mEnable && mixedInfo.filePath) { + relativePath = mixedInfo.filePath.replace(testCasesRootPath, ''); + } else { + relativePath = sourceFilePath.replace(testCasesRootPath, ''); + } + resultPath = path.join(outputDir, relativePath); + fs.mkdirSync(path.dirname(resultPath), {recursive: true}); + fs.writeFileSync(resultPath, mixedInfo.content); + if (this.mCustomProfiles.mEnableSourceMap && mixedInfo.sourceMap) { - fs.writeFileSync(path.join(outputDir, FileUtils.getFileName(sourceFilePath) + '.map'), + fs.writeFileSync(path.join(resultPath + '.map'), JSON.stringify(mixedInfo.sourceMap, null, JSON_TEXT_INDENT_LENGTH)); } + if (this.mCustomProfiles.mEnableNameCache && this.mCustomProfiles.mEnableNameCache) { - this.produceNameCache(mixedInfo.nameCache, sourceFilePath, outputDir); + this.produceNameCache(mixedInfo.nameCache, resultPath); } } } @@ -317,9 +341,10 @@ export class ArkObfuscator { * @param sourceFilePath * @param previousStageSourceMap * @param historyNameCache + * @param originalFilePath When filename obfuscation is enabled, it is used as the source code path. */ public async obfuscate(content: SourceFile | string, sourceFilePath: string, previousStageSourceMap?: sourceMap.RawSourceMap, - historyNameCache?: Map): Promise { + historyNameCache?: Map, originalFilePath?: string): Promise { let ast: SourceFile; let result: ObfuscationResultType = { content: undefined }; if (this.isObfsIgnoreFile(sourceFilePath)) { @@ -341,6 +366,10 @@ export class ArkObfuscator { renameIdentifierModule.historyNameCache = historyNameCache; } + if (this.mCustomProfiles.mRenameFileName?.mEnable ) { + orignalFilePathForSearching = originalFilePath ? originalFilePath : ast.fileName; + } + let transformedResult: TransformationResult = transform(ast, this.mTransformers, this.mCompilerOptions); ast = transformedResult.transformed[0] as SourceFile; @@ -350,8 +379,9 @@ export class ArkObfuscator { sourceMapGenerator = getSourceMapGenerator(sourceFilePath); } - this.createObfsPrinter().writeFile(ast, this.mTextWriter, sourceMapGenerator); + this.createObfsPrinter(ast.isDeclarationFile).writeFile(ast, this.mTextWriter, sourceMapGenerator); + result.filePath = ast.fileName; result.content = this.mTextWriter.getText(); if (this.mCustomProfiles.mEnableSourceMap && sourceMapGenerator) { @@ -364,7 +394,7 @@ export class ArkObfuscator { result.sourceMap = sourceMapJson; } - if (this.mCustomProfiles.mEnableNameCache) { + if (this.mCustomProfiles.mEnableNameCache && renameIdentifierModule.nameCache) { result.nameCache = Object.fromEntries(renameIdentifierModule.nameCache); } diff --git a/arkguard/src/configs/INameObfuscationOption.ts b/arkguard/src/configs/INameObfuscationOption.ts index 86675c51263f4888317d2cd2d551a33b1cb30ec0..539b7a0994164add0e80a9358de1eeb2a4ed3a4f 100644 --- a/arkguard/src/configs/INameObfuscationOption.ts +++ b/arkguard/src/configs/INameObfuscationOption.ts @@ -31,3 +31,12 @@ export interface INameObfuscationOption { readonly mKeepStringProperty?: boolean; } + +export interface IFileNameObfuscationOption { + + readonly mEnable: boolean; + + readonly mNameGeneratorType: NameGeneratorType; + + mReservedFileNames: string[]; +} \ No newline at end of file diff --git a/arkguard/src/configs/IOptions.ts b/arkguard/src/configs/IOptions.ts index 4056ba8d944df52323a6e12af19bb80557ff2eaf..3148979eff11f606bbdb34d2f0858b8fe53e25ef 100644 --- a/arkguard/src/configs/IOptions.ts +++ b/arkguard/src/configs/IOptions.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import type {INameObfuscationOption} from './INameObfuscationOption'; +import type {IFileNameObfuscationOption, INameObfuscationOption} from './INameObfuscationOption'; export interface IOptions { // Whether to generate compact code @@ -47,4 +47,6 @@ export interface IOptions { readonly apiSavedDir?: string; readonly applyReservedNamePath?: string; + + readonly mRenameFileName?: IFileNameObfuscationOption; } diff --git a/arkguard/src/transformers/TransformPlugin.ts b/arkguard/src/transformers/TransformPlugin.ts index f4d43dc606847051d56401be24b55185948aafc9..08aebf192b193f5881a647cac475e8d659354406 100644 --- a/arkguard/src/transformers/TransformPlugin.ts +++ b/arkguard/src/transformers/TransformPlugin.ts @@ -21,3 +21,13 @@ export interface TransformPlugin { order: number createTransformerFactory: (option: IOptions) => TransformerFactory; } + +export enum TransformerOrder { + SHORTHAND_PROPERTY_TRANSFORMER = 0, + DISABLE_CONSOLE_TRANSFORMER = 1, + DISABLE_HILOG_TRANSFORMER = 2, + SIMPLIFY_TRANSFORMER = 3, + RENAME_PROPERTIES_TRANSFORMER = 4, + RENAME_IDENTIFIER_TRANSFORMER = 5, + RENAME_FILE_NAME_TRANSFORMER = 6, +} \ No newline at end of file diff --git a/arkguard/src/transformers/layout/DisableConsoleTransformer.ts b/arkguard/src/transformers/layout/DisableConsoleTransformer.ts index ee1b5fe02daf0a439f0a6c72611f5caf47fc5da3..475cffbef437d9d506490d50c608c08c0c85d136 100644 --- a/arkguard/src/transformers/layout/DisableConsoleTransformer.ts +++ b/arkguard/src/transformers/layout/DisableConsoleTransformer.ts @@ -40,12 +40,13 @@ import type { import type {IOptions} from '../../configs/IOptions'; import type {TransformPlugin} from '../TransformPlugin'; +import {TransformerOrder} from '../TransformPlugin'; +import { NodeUtils } from '../../utils/NodeUtils'; namespace secharmony { - const TRANSFORMER_ORDER: number = 1; export let transformerPlugin: TransformPlugin = { 'name': 'disableConsolePlugin', - 'order': (1 << TRANSFORMER_ORDER), + 'order': (1 << TransformerOrder.DISABLE_CONSOLE_TRANSFORMER), 'createTransformerFactory': createDisableConsoleFactory }; @@ -60,7 +61,7 @@ namespace secharmony { return transformer; function transformer(node: Node): Node { - if (!isSourceFile(node) || node.fileName.endsWith('.d.ts')) { + if (!isSourceFile(node) || NodeUtils.isDeclarationFile(node)) { return node; } diff --git a/arkguard/src/transformers/layout/DisableHilogTransformer.ts b/arkguard/src/transformers/layout/DisableHilogTransformer.ts index 7b9193acfdbfb4ce2786cdbbca5da0d64d92d9a5..dd197aa23234fc985ab99e6f135932a754055757 100644 --- a/arkguard/src/transformers/layout/DisableHilogTransformer.ts +++ b/arkguard/src/transformers/layout/DisableHilogTransformer.ts @@ -40,14 +40,14 @@ import type { import type {IOptions} from '../../configs/IOptions'; import type {TransformPlugin} from '../TransformPlugin'; +import {TransformerOrder} from '../TransformPlugin'; import {OhPackType, isCommentedNode} from '../../utils/TransformUtil'; import {findOhImportStatement} from '../../utils/OhsUtil'; namespace secharmony { - const TRANSFORMER_ORDER: number = 2; export let transformerPlugin: TransformPlugin = { 'name': 'disableHilogPlugin', - 'order': (1 << TRANSFORMER_ORDER), + 'order': (1 << TransformerOrder.DISABLE_HILOG_TRANSFORMER), 'createTransformerFactory': createDisableHilogFactory }; diff --git a/arkguard/src/transformers/layout/SimplifyTransformer.ts b/arkguard/src/transformers/layout/SimplifyTransformer.ts index 5e5d3b3498bf084e7ab1b3b631d3c4641680b793..dcfc9185a6036a538cdbaf9c3eb510d9d71e5db7 100644 --- a/arkguard/src/transformers/layout/SimplifyTransformer.ts +++ b/arkguard/src/transformers/layout/SimplifyTransformer.ts @@ -39,18 +39,18 @@ import type { ModifiersArray, SourceFile, Block, - Expression + Expression, } from 'typescript'; import type { IOptions } from '../../configs/IOptions'; import type { TransformPlugin } from '../TransformPlugin'; +import {TransformerOrder} from '../TransformPlugin'; import { isCommentedNode, isSuperCallStatement } from '../../utils/TransformUtil'; namespace secharmony { - const TRANSFORMER_ORDER: number = 5; export let transformerPlugin: TransformPlugin = { 'name': 'simplifyPlugin', - 'order': (1 << TRANSFORMER_ORDER), + 'order': (1 << TransformerOrder.SIMPLIFY_TRANSFORMER), 'createTransformerFactory': createSimplifyFactory }; diff --git a/arkguard/src/transformers/rename/RenameFileNameTransformer.ts b/arkguard/src/transformers/rename/RenameFileNameTransformer.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3b29d3ce2df7509b81b5bad9cfcd5e58f96507b --- /dev/null +++ b/arkguard/src/transformers/rename/RenameFileNameTransformer.ts @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + factory, + isStringLiteral, + isExportDeclaration, + isImportDeclaration, + isSourceFile, + setParentRecursive, + visitEachChild, + isStructDeclaration, + SyntaxKind, + isConstructorDeclaration, +} from 'typescript'; + +import type { + CallExpression, + Expression, + ImportDeclaration, + ExportDeclaration, + Node, + StringLiteral, + TransformationContext, + Transformer, + StructDeclaration, + SourceFile, + ClassElement, + ImportCall, + TransformerFactory, +} from 'typescript'; + +import fs from 'fs'; +import path from 'path'; + +import type { IOptions } from '../../configs/IOptions'; +import type { TransformPlugin } from '../TransformPlugin'; +import { TransformerOrder } from '../TransformPlugin'; +import type { IFileNameObfuscationOption } from '../../configs/INameObfuscationOption'; +import { NameGeneratorType, getNameGenerator } from '../../generator/NameFactory'; +import type { INameGenerator, NameGeneratorOptions } from '../../generator/INameGenerator'; +import { FileUtils } from '../../utils/FileUtils'; +import { orignalFilePathForSearching } from '../../ArkObfuscator'; +namespace secharmony { + + // global mangled file name table used by all files in a project + export let globalFileNameMangledTable: Map = undefined; + + // used for file name cache + export let historyFileNameMangledTable: Map = undefined; + + let profile: IFileNameObfuscationOption | undefined; + let generator: INameGenerator | undefined; + let reservedFileNames: Set | undefined; + /** + * Rename Properties Transformer + * + * @param option obfuscation options + */ + const createRenameFileNameFactory = function (options: IOptions): TransformerFactory { + profile = options?.mRenameFileName; + if (!profile || !profile.mEnable) { + return null; + } + + return renameFileNameFactory; + + function renameFileNameFactory(context: TransformationContext): Transformer { + let options: NameGeneratorOptions = {}; + if (profile.mNameGeneratorType === NameGeneratorType.HEX) { + options.hexWithPrefixSuffix = true; + } + + generator = getNameGenerator(profile.mNameGeneratorType, options); + let tempReservedFileNameOrPath: string[] = profile?.mReservedFileNames ?? []; + let tempReservedFileName: string[] = ['.', '..', '']; + tempReservedFileNameOrPath.map(fileNameOrPath => { + if (fileNameOrPath && fileNameOrPath.length > 0) { + const directories = FileUtils.splitFilePath(fileNameOrPath); + directories.forEach(directory => { + tempReservedFileName.push(directory); + const pathOrExtension: PathAndExtension = removeFileSuffix(directory); + if (pathOrExtension.ext) { + tempReservedFileName.push(pathOrExtension.ext); + tempReservedFileName.push(pathOrExtension.path); + } + }); + } + }); + reservedFileNames = new Set(tempReservedFileName); + + return renameFileNameTransformer; + + function renameFileNameTransformer(node: Node): Node { + if (globalFileNameMangledTable === undefined) { + globalFileNameMangledTable = new Map(); + } + + let ret: Node = updateNodeInfo(node); + if (isSourceFile(ret)) { + const orignalAbsPath = ret.fileName; + const mangledAbsPath: string = getMangleCompletePath(orignalAbsPath); + ret.fileName = mangledAbsPath; + } + return setParentRecursive(ret, true); + } + + function updateNodeInfo(node: Node): Node { + if (isImportDeclaration(node) || isExportDeclaration(node)) { + return updateImportOrExportDeclaration(node); + } + + if (isImportCall(node)) { + return tryUpdateDynamicImport(node); + } + + if (isStructDeclaration(node)) { + return tryRemoveVirtualConstructor(node); + } + return visitEachChild(node, updateNodeInfo, context); + } + } + }; + + function updateImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration): ImportDeclaration | ExportDeclaration { + if (!node.moduleSpecifier) { + return node; + } + const mangledModuleSpecifier = renameStringLiteral(node.moduleSpecifier as StringLiteral); + if (isImportDeclaration(node)) { + return factory.updateImportDeclaration(node, node.modifiers, node.importClause, mangledModuleSpecifier as Expression, node.assertClause); + } else { + return factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, mangledModuleSpecifier as Expression, + node.assertClause); + } + } + + function isImportCall(n: Node): n is ImportCall { + return n.kind === SyntaxKind.CallExpression && (n).expression.kind === SyntaxKind.ImportKeyword; + } + + // dynamic import example: let module = import('./a') + function tryUpdateDynamicImport(node: CallExpression): CallExpression { + if (node.expression && node.arguments.length === 1 && isStringLiteral(node.arguments[0])) { + const obfuscatedArgument = [renameStringLiteral(node.arguments[0] as StringLiteral)]; + if (obfuscatedArgument[0] !== node.arguments[0]) { + return factory.updateCallExpression(node, node.expression, node.typeArguments, obfuscatedArgument); + } + } + return node; + } + + function renameStringLiteral(node: StringLiteral): Expression { + let expr: StringLiteral = renameFileName(node) as StringLiteral; + if (expr !== node) { + return factory.createStringLiteral(expr.text); + } + return node; + } + + function renameFileName(node: StringLiteral): Node { + let original: string = ''; + original = node.text; + original = original.replace(/\\/g, '/'); + + if (!canBeObfuscatedFilePath(original)) { + return node; + } + + let mangledFileName: string = getMangleIncompletePath(original); + if (mangledFileName === original) { + return node; + } + + return factory.createStringLiteral(mangledFileName); + } + + export function getMangleCompletePath(originalCompletePath: string): string { + originalCompletePath = toUnixPath(originalCompletePath); + const { path: filePathWithoutSuffix, ext: extension } = removeFileSuffix(originalCompletePath); + const mangleFilePath = manglFileName(filePathWithoutSuffix); + return mangleFilePath + extension; + } + + function getMangleIncompletePath(orignalPath: string): string | undefined { + const pathAndExtension : PathAndExtension | undefined = tryValidateFileExisting(orignalPath); + if (!pathAndExtension) { + return orignalPath; + } + + if (pathAndExtension.ext) { + const mangleFilePath = manglFileName(pathAndExtension.path); + return mangleFilePath; + } else { + const { path: filePathWithoutSuffix, ext: extension } = removeFileSuffix(pathAndExtension.path); + const mangleFilePath = manglFileName(filePathWithoutSuffix); + return mangleFilePath + extension; + } + } + + function manglFileName(orignalPath: string): string { + const originalFileNameSegments: string[] = FileUtils.splitFilePath(orignalPath); + const mangledSegments: string[] = originalFileNameSegments.map(originalSegment => mangleFileNamePart(originalSegment)); + let mangledFileName: string = mangledSegments.join('/'); + return mangledFileName; + } + + function mangleFileNamePart(original: string): string { + if (reservedFileNames.has(original)) { + return original; + } + + const historyName: string = historyFileNameMangledTable?.get(original); + let mangledName: string = historyName ? historyName : globalFileNameMangledTable.get(original); + + while (!mangledName) { + mangledName = generator.getName(); + if (mangledName === original || reservedFileNames.has(mangledName)) { + mangledName = null; + continue; + } + + let reserved: string[] = [...globalFileNameMangledTable.values()]; + if (reserved.includes(mangledName)) { + mangledName = null; + continue; + } + + if (historyFileNameMangledTable && [...historyFileNameMangledTable.values()].includes(mangledName)) { + mangledName = null; + continue; + } + } + globalFileNameMangledTable.set(original, mangledName); + return mangledName; + } + + export let transformerPlugin: TransformPlugin = { + 'name': 'renamePropertiesPlugin', + 'order': (1 << TransformerOrder.RENAME_FILE_NAME_TRANSFORMER), + 'createTransformerFactory': createRenameFileNameFactory + }; +} + +export = secharmony; + +function canBeObfuscatedFilePath(filePath: string): boolean { + return path.isAbsolute(filePath) || FileUtils.isRelativePath(filePath); +} + +// typescript doesn't add the json extension. +const extensionOrder: string[] = ['.ets', '.ts', '.d.ets', '.d.ts', '.js']; + +function tryValidateFileExisting(importPath: string): PathAndExtension | undefined { + let fileAbsPath: string = ''; + if (path.isAbsolute(importPath)) { + fileAbsPath = importPath; + } else { + fileAbsPath = path.join(path.dirname(orignalFilePathForSearching), importPath); + } + + const filePathExtensionLess: string = path.normalize(fileAbsPath); + for (let ext of extensionOrder) { + const targetPath = filePathExtensionLess + ext; + if (fs.existsSync(targetPath)) { + return {path: importPath, ext: ext}; + } + } + + // all suffixes are not matched, search this file directly. + if (fs.existsSync(filePathExtensionLess)) { + return { path: importPath, ext: undefined }; + } + return undefined; +} + +interface PathAndExtension { + path: string; + ext: string | undefined; +} + +const fileExtensions: string[] = ['.d.ets', '.ets', '.d.ts', '.ts', '.js', '.json']; + +function removeFileSuffix(filePath: string): PathAndExtension { + for (let ext of fileExtensions) { + if (filePath.endsWith(ext)) { + const filePathWithoutSuffix: string = filePath.replace(new RegExp(`${ext}$`), ''); + return { path: filePathWithoutSuffix, ext: ext }; + } + } + return { path: filePath, ext: undefined }; +} + +function tryRemoveVirtualConstructor(node: StructDeclaration): StructDeclaration { + const sourceFile = getSourceFileOfNode(node); + const tempStructMembers: ClassElement[] = []; + if (sourceFile && sourceFile.isDeclarationFile && isInETSFile(sourceFile)) { + for (let member of node.members) { + // @ts-ignore + if (!isConstructorDeclaration(member) || !member.virtual) { + tempStructMembers.push(member); + } + } + const structMembersWithVirtualConstructor = factory.createNodeArray(tempStructMembers); + return factory.updateStructDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, structMembersWithVirtualConstructor); + } + return node; +} + +function getSourceFileOfNode(node: Node): SourceFile { + while (node && node.kind !== SyntaxKind.SourceFile) { + node = node.parent; + } + return node; +} + +function isInETSFile(node: Node | undefined): boolean { + return !!node && getSourceFileOfNode(node).fileName.endsWith('.ets'); +} + +function toUnixPath(data: string): string { + if (/^win/.test(require('os').platform())) { + const fileTmps: string[] = data.split(path.sep); + const newData: string = path.posix.join(...fileTmps); + return newData; + } + return data; +} diff --git a/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts b/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts index 412928c20a72f7ce6c44618ab1b818d8138972ab..56a394ed9cc29710cf7e53affd22b28998262cf3 100644 --- a/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts +++ b/arkguard/src/transformers/rename/RenameIdentifierTransformer.ts @@ -54,6 +54,7 @@ import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGe import type {IOptions} from '../../configs/IOptions'; import type {INameObfuscationOption} from '../../configs/INameObfuscationOption'; import type {TransformPlugin} from '../TransformPlugin'; +import {TransformerOrder} from '../TransformPlugin'; import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory'; import {TypeUtils} from '../../utils/TypeUtils'; import {collectIdentifiers} from '../../utils/TransformUtil'; @@ -112,7 +113,7 @@ namespace secharmony { * @param node ast node of a file. */ function renameTransformer(node: Node): Node { - if (!isSourceFile(node)) { + if (!isSourceFile(node) || NodeUtils.isDeclarationFile(node)) { return node; } @@ -383,10 +384,9 @@ namespace secharmony { return !enableTopLevel && isGlobalScope(scope); } - const TRANSFORMER_ORDER: number = 9; export let transformerPlugin: TransformPlugin = { 'name': 'renameIdentifierPlugin', - 'order': (1 << TRANSFORMER_ORDER), + 'order': (1 << TransformerOrder.RENAME_IDENTIFIER_TRANSFORMER), 'createTransformerFactory': createRenameIdentifierFactory }; diff --git a/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts b/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts index 2b9097bfe7f45dabf8a13f2caf9d40cc8b3ae16c..778338075e8c311ccfc8067ee6cc3d4ea919f27b 100644 --- a/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts +++ b/arkguard/src/transformers/rename/RenamePropertiesTransformer.ts @@ -28,7 +28,8 @@ import { isTypeNode, setParentRecursive, visitEachChild, - isStringLiteral + isStringLiteral, + isSourceFile } from 'typescript'; import type { @@ -50,6 +51,7 @@ import type {INameObfuscationOption} from '../../configs/INameObfuscationOption' import type {INameGenerator, NameGeneratorOptions} from '../../generator/INameGenerator'; import {getNameGenerator, NameGeneratorType} from '../../generator/NameFactory'; import type {TransformPlugin} from '../TransformPlugin'; +import {TransformerOrder} from '../TransformPlugin'; import {NodeUtils} from '../../utils/NodeUtils'; import {collectPropertyNamesAndStrings, isViewPUBasedClass} from '../../utils/OhsUtil'; @@ -92,6 +94,10 @@ namespace secharmony { return renamePropertiesTransformer; function renamePropertiesTransformer(node: Node): Node { + if (isSourceFile(node) && NodeUtils.isDeclarationFile(node)) { + return node; + } + collectReservedNames(node); if (globalMangledTable === undefined) { globalMangledTable = new Map(); @@ -262,10 +268,9 @@ namespace secharmony { } }; - const TRANSFORMER_ORDER: number = 6; export let transformerPlugin: TransformPlugin = { 'name': 'renamePropertiesPlugin', - 'order': (1 << TRANSFORMER_ORDER), + 'order': (1 << TransformerOrder.RENAME_PROPERTIES_TRANSFORMER), 'createTransformerFactory': createRenamePropertiesFactory }; } diff --git a/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts b/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts index 4cd2f3ab06f9e9f29f7cb69dfc194b2a7c983abe..070ea5eb711153ad5e739307961e06e53c42b23a 100644 --- a/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts +++ b/arkguard/src/transformers/rename/ShorthandPropertyTransformer.ts @@ -18,6 +18,7 @@ import { isBindingElement, isObjectBindingPattern, isShorthandPropertyAssignment, + isSourceFile, setParentRecursive, visitEachChild } from 'typescript'; @@ -33,6 +34,7 @@ import type { import type {INameObfuscationOption} from '../../configs/INameObfuscationOption'; import type {TransformPlugin} from '../TransformPlugin'; +import {TransformerOrder} from '../TransformPlugin'; import type {IOptions} from '../../configs/IOptions'; import {NodeUtils} from '../../utils/NodeUtils'; @@ -49,6 +51,9 @@ namespace secharmony { return shorthandPropertyTransformer; function shorthandPropertyTransformer(node: Node): Node { + if (isSourceFile(node) && NodeUtils.isDeclarationFile(node)) { + return node; + } return setParentRecursive(transformShortHandProperty(node), true); } @@ -92,10 +97,9 @@ namespace secharmony { } }; - const TRANSFORMER_ORDER: number = 0; export let transformerPlugin: TransformPlugin = { 'name': 'ShortHandPropertyTransformer', - 'order': (1 << TRANSFORMER_ORDER), + 'order': (1 << TransformerOrder.SHORTHAND_PROPERTY_TRANSFORMER), 'createTransformerFactory': createShorthandPropertyTransformerFactory, }; } diff --git a/arkguard/src/utils/FileUtils.ts b/arkguard/src/utils/FileUtils.ts index abc9dbac6c9666688b4e71bc80431de308557129..aebfc92c0166db4676a858100a034ef6ae023a6f 100644 --- a/arkguard/src/utils/FileUtils.ts +++ b/arkguard/src/utils/FileUtils.ts @@ -115,4 +115,31 @@ export class FileUtils { return filePath.slice(prefix.length); } + + public static splitFilePath(filePath: string): string[] { + if (!filePath.includes('\\') && !filePath.includes('\/')) { + return [filePath]; + } + const directories = filePath.split(/[\/\\]/); + const output: string[] = []; + /* path: /foo//bar; the target output is ['', 'foo', '', 'bar']. + * if the first empty string is deleted, the path joining of the Linux platform folder is 'foo/bar'. + */ + if (directories.length > 0 && directories[0] === '') { + output.push(''); + } + + output.push(...(directories.filter(part => part !== ''))); + return directories; + } + + static relativePathBegins: string[] = ['./', '../', '.\\', '..\\']; + public static isRelativePath(filePath: string): boolean { + for (const bebin of this.relativePathBegins) { + if (filePath.startsWith(bebin)) { + return true; + } + } + return false; + } } diff --git a/arkguard/src/utils/NodeUtils.ts b/arkguard/src/utils/NodeUtils.ts index 11d24da2002733fdd1c2c39da1352c91ffc3ed47..775d2eba2e4a169f1be1e3fb030c589dace3e7d6 100644 --- a/arkguard/src/utils/NodeUtils.ts +++ b/arkguard/src/utils/NodeUtils.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import type {Expression, Node, ObjectBindingPattern} from 'typescript'; +import type {Expression, Node, ObjectBindingPattern, SourceFile} from 'typescript'; import { isBindingElement, isCallExpression, @@ -160,4 +160,8 @@ export class NodeUtils { const initializer: Expression = node.parent.initializer; return initializer && isCallExpression(initializer); } + + public static isDeclarationFile(node: SourceFile): boolean { + return node.isDeclarationFile; + } } diff --git a/arkguard/test/grammar/rename_file_name/declaration_file/declaration_struct.d.ets b/arkguard/test/grammar/rename_file_name/declaration_file/declaration_struct.d.ets new file mode 100644 index 0000000000000000000000000000000000000000..b27acc5f311e60fec7e981e7261f7d378d4b23af --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/declaration_file/declaration_struct.d.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Componnt +export declare struct MainPage { + constructor(name: string) + @State + massage: string; + build(): void; +} + +/** + * comments + */ +export declare class DogClass { + food: number; +} + +export const value99: number = 2; \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/declaration_file/export_func_class.d.ts b/arkguard/test/grammar/rename_file_name/declaration_file/export_func_class.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..5b563e8481d7e547b8daa7072be846bc00c6497b --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/declaration_file/export_func_class.d.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export declare function declaration_func(n1: number, n2: number): void; + +export declare class declaration_class{} + diff --git a/arkguard/test/grammar/rename_file_name/declaration_file/folder_declaration/export_var.d.ts b/arkguard/test/grammar/rename_file_name/declaration_file/folder_declaration/export_var.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..b145a5560a2b4dc93d87cce67f660212ff040b51 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/declaration_file/folder_declaration/export_var.d.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export let tomAddr: string; +export let tomAge: number; \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/declaration_file/import_declaration_file.d.ts b/arkguard/test/grammar/rename_file_name/declaration_file/import_declaration_file.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..2d6a8f6b1f5a6023a7dce533cb3ea341ebbee13a --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/declaration_file/import_declaration_file.d.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { declaration_class, declaration_func } from './export_func_class' +import { tomAddr, tomAge } from './folder_declaration/export_var' +import { MainPage, DogClass } from './declaration_struct' + +declare function printName(name: string): void; + +declare function printFunc(funcName: string): void; + +declare function defaultFunction01(para1: string, para2: number): void + +declare class myClassTemp { + tempPapa1: string; + tempPara2: number; +} \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/esm-module-js/export_default.js b/arkguard/test/grammar/rename_file_name/esm-module-js/export_default.js new file mode 100644 index 0000000000000000000000000000000000000000..c215285bfe53ad70ab9ef215001bad8752fa20dc --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-js/export_default.js @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class ClassName { + classProp1 = 0; + foo() {}; +} diff --git a/arkguard/test/grammar/rename_file_name/esm-module-js/export_list_js.js b/arkguard/test/grammar/rename_file_name/esm-module-js/export_list_js.js new file mode 100644 index 0000000000000000000000000000000000000000..a477ebd63bc08f58442240b2b01a6aad6b876ac2 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-js/export_list_js.js @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let variable1 = 1; +let variable2 = 2; +export { variable1 as name1, variable2 as name2}; +export { variable1 as newVariable1 }; diff --git a/arkguard/test/grammar/rename_file_name/esm-module-js/folder/export_declarations.js b/arkguard/test/grammar/rename_file_name/esm-module-js/folder/export_declarations.js new file mode 100644 index 0000000000000000000000000000000000000000..6ce2ff116447147ed5ac6c47c1783e13948db0c7 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-js/folder/export_declarations.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export let value01 = 1, value02 = 2; + +export const value03 = 3, value04 = 4/*, … */; // also var, let + +export function function01() { + return 10; +} + +export class Actor { + name = 'asuss'; + age = 19; +} + +export function* generatorFunctionName01() { + let acator = new Actor(); + acator.age += 1; + yield acator; +} diff --git a/arkguard/test/grammar/rename_file_name/esm-module-js/folder/whole_modue.js b/arkguard/test/grammar/rename_file_name/esm-module-js/folder/whole_modue.js new file mode 100644 index 0000000000000000000000000000000000000000..e88f797f9e943eb07e1b2cd06e1052ce0f114abd --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-js/folder/whole_modue.js @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export let var1 = 10; +export function foo1() { + return 20; +} \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/esm-module-js/import_js_assert.js b/arkguard/test/grammar/rename_file_name/esm-module-js/import_js_assert.js new file mode 100644 index 0000000000000000000000000000000000000000..9f1370832042e1109a31c3983c5f75e8dfa187bd --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-js/import_js_assert.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const assert = require('assert'); + +// default import +import defaultExport from "./export_default"; +let classObj = new defaultExport(); +assert(classObj.classProp1 === 0, 'success'); + +// namespace import +import * as namespace01 from "./folder/export_declarations"; +assert(namespace01.function01() === 10, 'success'); + +import { value01, generatorFunctionName01 } from "./folder/export_declarations.js"; +assert(value01 === 1, 'success'); +const generator = generatorFunctionName01(); +assert(generator.next().value['age'] === 20, 'success'); + +// rename an export when importing it +import { value03 as value03Alias } from "./folder/export_declarations"; +assert(value03Alias === 3, 'success'); + +// import multiple names from the same module. +import { name1 , name2 as alias2 } from "./export_list_js"; +assert(name1 === 1, 'success'); +assert(alias2 === 2, 'success'); + +// static Import +import "./folder/whole_modue"; diff --git a/arkguard/test/grammar/rename_file_name/esm-module-ts/export_default.ts b/arkguard/test/grammar/rename_file_name/esm-module-ts/export_default.ts new file mode 100644 index 0000000000000000000000000000000000000000..c215285bfe53ad70ab9ef215001bad8752fa20dc --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-ts/export_default.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default class ClassName { + classProp1 = 0; + foo() {}; +} diff --git a/arkguard/test/grammar/rename_file_name/esm-module-ts/export_list.ts b/arkguard/test/grammar/rename_file_name/esm-module-ts/export_list.ts new file mode 100644 index 0000000000000000000000000000000000000000..0eb75090c8532865de890214297dde19e33b17df --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-ts/export_list.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let variable1 = 1; +let variable2 = 2; +export { variable1 as var1, variable2 as var2 }; +export { variable1 as newVariable1 }; diff --git a/arkguard/test/grammar/rename_file_name/esm-module-ts/folder/export_declarations.ts b/arkguard/test/grammar/rename_file_name/esm-module-ts/folder/export_declarations.ts new file mode 100644 index 0000000000000000000000000000000000000000..39901155c6c39c9003cbdd50d07aa91b87206354 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-ts/folder/export_declarations.ts @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export let value01 = 1, value02 = 2; + +export const value03 = 3, value04 = 4/*, … */; // also var, let + +export function function01() { + return 10; +} + +export class Actor { + name: string = 'asuss'; + age: number = 19; +} + +export function* generatorFunctionName01() { + let acator = new Actor(); + acator.age += 1; + yield acator; +} + +export const { value05, name01: bar } = {value05: 11, name01: 'jack'}; \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/esm-module-ts/folder/whole_modue.ts b/arkguard/test/grammar/rename_file_name/esm-module-ts/folder/whole_modue.ts new file mode 100644 index 0000000000000000000000000000000000000000..4f2ada13a47099a0d1745fd0b9bf18a48d0e8554 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-ts/folder/whole_modue.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export let var1 = 10; + +export function foo1() { + return 20; +} \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/esm-module-ts/import_ts_assert.ts b/arkguard/test/grammar/rename_file_name/esm-module-ts/import_ts_assert.ts new file mode 100644 index 0000000000000000000000000000000000000000..1532737ecf513e884b294e0c2ea99167d0a08bf6 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-ts/import_ts_assert.ts @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const assert = require('assert'); + +// default import +import defaultExport from "./export_default"; +let classObj = new defaultExport(); +assert(classObj.classProp1 === 0, 'success'); + +// namespace import +// namespace import +import * as namespace01 from "./folder/export_declarations"; +assert(namespace01.function01() === 10, 'success'); + +import { value01, generatorFunctionName01 } from "./folder//export_declarations"; +assert(value01 === 1, 'success'); +const generator = generatorFunctionName01(); +assert(generator.next().value['age'] === 20, 'success'); + +// rename an export when importing it +import { value03 as value03Alias } from "./folder\\export_declarations"; +assert(value03Alias === 3, 'success'); + +// import multiple names from the same module. +import { var1 , var2 as alias2 } from ".\\export_list"; +assert(var1 === 1, 'success'); +assert(alias2 === 2, 'success'); + +// import indirect module +import { value05, bar } from './indirect_export' +assert(value05 === 11, 'success'); +assert(bar === 'jack', 'success'); + +// static Import +import "./folder/whole_modue"; diff --git a/arkguard/test/grammar/rename_file_name/esm-module-ts/indirect_export.ts b/arkguard/test/grammar/rename_file_name/esm-module-ts/indirect_export.ts new file mode 100644 index 0000000000000000000000000000000000000000..2d91c7ab42215bfbf92854232e11a697aca7b8de --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/esm-module-ts/indirect_export.ts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { value05, bar } from './folder/export_declarations' \ No newline at end of file diff --git a/arkguard/test/grammar/rename_file_name/index.ts b/arkguard/test/grammar/rename_file_name/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..5e770d4c3c5b392fc0707f2048e8e64e17b493f3 --- /dev/null +++ b/arkguard/test/grammar/rename_file_name/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function foo() { + +} + +function main() { + +} \ No newline at end of file diff --git a/arkguard/scripts/grammarTestConfig.json b/arkguard/test/grammar/rename_file_name/obfConfig.json similarity index 52% rename from arkguard/scripts/grammarTestConfig.json rename to arkguard/test/grammar/rename_file_name/obfConfig.json index 3ce9b7e20e8acce4c5e01eba0b53e4514d1db916..dbab2012dc8c2077c3a4faaff8405ed07fcdcbe1 100644 --- a/arkguard/scripts/grammarTestConfig.json +++ b/arkguard/test/grammar/rename_file_name/obfConfig.json @@ -1,7 +1,7 @@ { "mCompact": false, "mRemoveComments": false, - "mOutputDir": "../test/local", + "mOutputDir": "../../local", "mDisableHilog": false, "mDisableConsole": false, "mSimplify": false, @@ -9,22 +9,17 @@ "mEnable": true, "mNameGeneratorType": 1, "mDictionaryList": [], - "mReservedNames": [ - "moduleName01", - "stringLiteralObj02", - "Interface11", - "class11", - "enum11", - "Object11" - ], + "mReservedNames": [], "mRenameProperties": true, - "mReservedProperties": [ - "strictEqual", - "readFileSync" - ], + "mReservedProperties": [], "mKeepStringProperty": true }, "mEnableSourceMap": false, "mEnableNameCache": false, - "mTopLevel": true + "mTopLevel":true, + "mRenameFileName": { + "mEnable": true, + "mNameGeneratorType": 1, + "mReservedFileNames": ["local", "rename_file_name", "index"] + } } \ No newline at end of file