DictionaryIdentifierNamesGenerator refactoring

This commit is contained in:
sanex3339
2019-12-31 12:40:29 +03:00
parent c87a6262a6
commit 36918c351c
16 changed files with 30890 additions and 161 deletions
+1 -1
View File
@@ -261,7 +261,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
)
.option(
'--identifiers-dictionary <list> (comma separated, without whitespaces)',
'Identifiers dictionary (comma separated)',
'Identifiers dictionary (comma separated) for `--identifier-names-generator dictionary` option',
ArraySanitizer
)
.option(
@@ -6,12 +6,17 @@ import { IOptions } from '../../../interfaces/options/IOptions';
import { IdentifierNamesGenerator } from '../../../enums/generators/identifier-names-generators/IdentifierNamesGenerator';
import { DictionaryIdentifierNamesGenerator } from '../../../generators/identifier-names-generators/DictionaryIdentifierNamesGenerator';
import { HexadecimalIdentifierNamesGenerator } from '../../../generators/identifier-names-generators/HexadecimalIdentifierNamesGenerator';
import { MangledIdentifierNamesGenerator } from '../../../generators/identifier-names-generators/MangledIdentifierNamesGenerator';
import { DictionaryNamesGenerator } from '../../../generators/identifier-names-generators/DictionaryNamesGenerator';
export const generatorsModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// identifier name generators
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.IIdentifierNamesGenerator)
.to(DictionaryIdentifierNamesGenerator)
.inSingletonScope()
.whenTargetNamed(IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator);
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.IIdentifierNamesGenerator)
.to(HexadecimalIdentifierNamesGenerator)
.inSingletonScope()
@@ -22,11 +27,6 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
.inSingletonScope()
.whenTargetNamed(IdentifierNamesGenerator.MangledIdentifierNamesGenerator);
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.IIdentifierNamesGenerator)
.to(DictionaryNamesGenerator)
.inSingletonScope()
.whenTargetNamed(IdentifierNamesGenerator.DictionaryNamesGenerator);
// identifier name generator factory
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
.toFactory<IIdentifierNamesGenerator>((context: interfaces.Context): (options: IOptions) => IIdentifierNamesGenerator => {
@@ -40,6 +40,14 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
let identifierNamesGenerator: IIdentifierNamesGenerator;
switch (options.identifierNamesGenerator) {
case IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
);
break;
case IdentifierNamesGenerator.MangledIdentifierNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
@@ -47,14 +55,6 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
);
break;
case IdentifierNamesGenerator.DictionaryNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.DictionaryNamesGenerator
);
break;
case IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator:
default:
@@ -1,5 +1,5 @@
export enum IdentifierNamesGenerator {
DictionaryIdentifierNamesGenerator = 'dictionary',
HexadecimalIdentifierNamesGenerator = 'hexadecimal',
MangledIdentifierNamesGenerator = 'mangled',
DictionaryNamesGenerator = 'dictionary'
MangledIdentifierNamesGenerator = 'mangled'
}
@@ -0,0 +1,128 @@
import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
@injectable()
export class DictionaryIdentifierNamesGenerator extends AbstractIdentifierNamesGenerator {
/**
* @type {IArrayUtils}
*/
private readonly arrayUtils: IArrayUtils;
/**
* @type {string[]}
*/
private identifierNames: string[] = [];
/**
* @type {IterableIterator<string>}
*/
private identifiersIterator: IterableIterator<string>;
/**
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {IArrayUtils} arrayUtils
*/
constructor (
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils,
) {
super(randomGenerator, options);
this.arrayUtils = arrayUtils;
this.identifierNames = this.getInitialIdentifierNames(this.options.identifiersDictionary);
this.identifiersIterator = this.identifierNames.values();
}
/**
* @param {string} identifierName
* @returns {string | null}
*/
private static incrementIdentifierName (identifierName: string): string | null {
let newIdentifierName: string = '';
let isSuccess: boolean = false;
for (const character of identifierName) {
if (!isSuccess && character === character.toUpperCase()) {
newIdentifierName += character.toLowerCase();
} else if (!isSuccess && character === character.toLowerCase()) {
newIdentifierName += character.toUpperCase();
isSuccess = true;
} else {
newIdentifierName += character;
}
}
if (isSuccess) {
return newIdentifierName;
}
return null;
}
public generate (): string {
if (!this.identifierNames.length) {
throw new Error('Too many identifiers in the code, add more words to identifiers dictionary');
}
const iteratorResult: IteratorResult<string> = this.identifiersIterator.next();
if (!iteratorResult.done) {
return iteratorResult.value;
}
this.identifierNames = this.getIncrementedIdentifierNames(this.identifierNames);
this.identifiersIterator = this.identifierNames.values();
return this.generate();
}
/**
* @returns {string}
*/
public generateWithPrefix (): string {
const prefix: string = this.options.identifiersPrefix ?
`${this.options.identifiersPrefix}_`
: '';
const identifierName: string = this.generate();
return `${prefix}${identifierName}`.replace('__', '_');
}
/**
* @param {string[]} identifierNames
* @returns {string[]}
*/
private getInitialIdentifierNames (identifierNames: string[]): string[] {
const formattedIdentifierNames: string[] = identifierNames
.map((identifierName: string) => identifierName.toLowerCase());
return this.arrayUtils.shuffle(formattedIdentifierNames);
}
/**
* @param {string[]} identifierNames
* @returns {string[]}
*/
private getIncrementedIdentifierNames (identifierNames: string[]): string[] {
const formattedIdentifierNames: string[] = [];
for (const identifierName of identifierNames) {
const newIdentifierName: string | null = DictionaryIdentifierNamesGenerator
.incrementIdentifierName(identifierName);
if (newIdentifierName) {
formattedIdentifierNames.push(newIdentifierName);
}
}
return this.arrayUtils.shuffle(formattedIdentifierNames);
}
}
@@ -1,118 +0,0 @@
import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { AbstractIdentifierNamesGenerator } from './AbstractIdentifierNamesGenerator';
@injectable()
export class DictionaryNamesGenerator extends AbstractIdentifierNamesGenerator {
/**
* @type {string[]}
*/
private identifiers: string[] = [];
/**
* @type {IterableIterator<string>}
*/
private it: IterableIterator<string>;
/**
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(randomGenerator, options);
for (const dict of options.identifiersDictionary) {
this.identifiers[this.identifiers.length] = dict.toLowerCase();
}
this.shuffle(this.identifiers);
this.it = this.identifiers.values();
}
/**
* @param {string} str
* @returns {string | null}
*/
private static increment (str: string): string | null {
let newString: string = "";
let success: boolean = false;
for (const i of str) {
if (!success && i === i.toUpperCase()) {
newString += i.toLowerCase();
} else if (!success && i === i.toLowerCase()) {
newString += i.toUpperCase();
success = true;
} else {
newString += i;
}
}
if (success) {
return newString;
}
return null;
}
/**
* @param {string[]} arr
* @returns {string[]}
*/
private static incrementArr (arr: string[]): string[] {
const newArr: string[] = [];
for (const dict of arr) {
const newDict: string | null = DictionaryNamesGenerator.increment(dict);
if (newDict) {
newArr[newArr.length] = newDict;
}
}
return newArr;
}
public generate (): string {
if (this.identifiers.length === 0) {
throw new Error("identifiersDictionary is empty. Add more words to identifiersDictionary");
}
let itResult: IteratorResult<string> = this.it.next();
if (itResult.done) {
this.identifiers = DictionaryNamesGenerator.incrementArr(this.identifiers);
this.shuffle(this.identifiers);
this.it = this.identifiers.values();
itResult = this.it.next();
}
if (itResult.done) {
throw new Error("Too many identifiers in JS code, add more words to identifiersDictionary");
}
const identifierName: string = itResult.value;
return identifierName;
}
/**
* @returns {string}
*/
public generateWithPrefix (): string {
const prefix: string = this.options.identifiersPrefix ?
`${this.options.identifiersPrefix}_`
: '';
const identifierName: string = this.generate();
return `${prefix}${identifierName}`.replace('__', '_');;
}
/**
* @param {string[]} arr
*/
private shuffle (arr: string[]): void {
for (let i: number = arr.length - 1; i > 0; i--) {
const j: number = this.randomGenerator.getRandomInteger(0, i);
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
}
+1 -1
View File
@@ -15,8 +15,8 @@ export interface IOptions {
readonly disableConsoleOutput: boolean;
readonly domainLock: string[];
readonly identifierNamesGenerator: IdentifierNamesGenerator;
readonly identifiersPrefix: string;
readonly identifiersDictionary: string[];
readonly identifiersPrefix: string;
readonly inputFileName: string;
readonly log: boolean;
readonly renameGlobals: boolean;
+7 -2
View File
@@ -2,6 +2,7 @@ import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
import {
ArrayNotEmpty,
ArrayUnique,
IsArray,
IsBoolean,
@@ -107,9 +108,9 @@ export class Options implements IOptions {
* @type {IdentifierNamesGenerator}
*/
@IsIn([
IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
IdentifierNamesGenerator.DictionaryNamesGenerator
IdentifierNamesGenerator.MangledIdentifierNamesGenerator
])
public readonly identifierNamesGenerator!: IdentifierNamesGenerator;
@@ -124,6 +125,10 @@ export class Options implements IOptions {
@IsString({
each: true
})
@ValidateIf((options: IOptions) =>
options.identifierNamesGenerator === IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
)
@ArrayNotEmpty()
public readonly identifiersDictionary!: string[];
/**
+1 -1
View File
@@ -18,7 +18,7 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
exclude: [],
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
identifiersPrefix: '',
identifiersDictionary: ["qwertyuiop", "asdfghjkl", "zxcvbnm"],
identifiersDictionary: [],
inputFileName: '',
log: false,
renameGlobals: false,
+1 -1
View File
@@ -17,7 +17,7 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
exclude: [],
identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
identifiersPrefix: '',
identifiersDictionary: ["qwertyuiop", "asdfghjkl", "zxcvbnm"],
identifiersDictionary: [],
inputFileName: '',
log: false,
renameGlobals: false,
@@ -50,6 +50,10 @@ export class StringArrayStorage extends ArrayStorage <string> {
public initialize (): void {
super.initialize();
if (!this.options.stringArray) {
return;
}
const baseStringArrayName: string = this.identifierNamesGenerator
.generate(StringArrayStorage.stringArrayNameLength);
const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator