123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- import { injectable, inject } from 'inversify';
- import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
- import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
- import { IEncodedValue } from '../../../interfaces/node-transformers/IEncodedValue';
- import { IOptions } from '../../../interfaces/options/IOptions';
- import { IStorage } from '../../../interfaces/storages/IStorage';
- import { StringArrayEncoding } from '../../../enums/StringArrayEncoding';
- import { AbstractReplacer } from './AbstractReplacer';
- import { CryptUtils } from '../../../utils/CryptUtils';
- import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
- import { Utils } from '../../../utils/Utils';
- @injectable()
- export class StringLiteralReplacer extends AbstractReplacer {
- /**
- * @type {number}
- */
- private static readonly minimumLengthForStringArray: number = 3;
- /**
- * @type {IStorage<ICustomNodeGroup>}
- */
- private readonly customNodeGroupStorage: IStorage<ICustomNodeGroup>;
- /**
- * @type {string[]}
- */
- private readonly rc4Keys: string[];
- /**
- * @type {Map<string, string>}
- */
- private readonly stringLiteralCache: Map <string, string> = new Map();
- /**
- * @type {Map<string, string>}
- */
- private readonly stringLiteralHexadecimalIndexCache: Map <string, string> = new Map();
- /**
- * @type {IStorage<string>}
- */
- private readonly stringArrayStorage: IStorage<string>;
- /**
- * @param customNodeGroupStorage
- * @param stringArrayStorage
- * @param options
- */
- constructor (
- @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: IStorage<ICustomNodeGroup>,
- @inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStorage<string>,
- @inject(ServiceIdentifiers.IOptions) options: IOptions
- ) {
- super(options);
- this.customNodeGroupStorage = customNodeGroupStorage;
- this.stringArrayStorage = stringArrayStorage;
- this.rc4Keys = RandomGeneratorUtils.getRandomGenerator()
- .n(() => RandomGeneratorUtils.getRandomGenerator().string({length: 4}), 50);
- }
- /**
- * @param nodeValue
- * @returns {string}
- */
- public replace (nodeValue: string): string {
- const usingStringArray: boolean = (
- this.options.stringArray &&
- nodeValue.length >= StringLiteralReplacer.minimumLengthForStringArray &&
- RandomGeneratorUtils.getRandomFloat(0, 1) <= this.options.stringArrayThreshold
- );
- const cacheKey: string = `${nodeValue}-${String(usingStringArray)}`;
- if (this.stringLiteralCache.has(cacheKey) && this.options.stringArrayEncoding !== StringArrayEncoding.rc4) {
- return <string>this.stringLiteralCache.get(cacheKey);
- }
- let result: string;
- if (usingStringArray) {
- result = this.replaceStringLiteralWithStringArrayCall(nodeValue);
- } else {
- result = `'${Utils.stringToUnicodeEscapeSequence(nodeValue, !this.options.unicodeEscapeSequence)}'`;
- }
- this.stringLiteralCache.set(cacheKey, result);
- return result;
- }
- /**
- * @param value
- * @return {string}
- */
- private getArrayHexadecimalIndex (value: string): string {
- if (this.stringLiteralHexadecimalIndexCache.has(value)) {
- return <string>this.stringLiteralHexadecimalIndexCache.get(value);
- }
- const stringArrayStorageLength: number = this.stringArrayStorage.getLength();
- const hexadecimalIndex: string = `${Utils.hexadecimalPrefix}${Utils.decToHex(stringArrayStorageLength)}`;
- this.stringArrayStorage.set(stringArrayStorageLength, value);
- this.stringLiteralHexadecimalIndexCache.set(value, hexadecimalIndex);
- return hexadecimalIndex;
- }
- /**
- * @param value
- * @returns {IEncodedValue}
- */
- private getEncodedValue (value: string): IEncodedValue {
- let encodedValue: string,
- key: string | undefined;
- switch (this.options.stringArrayEncoding) {
- case StringArrayEncoding.rc4:
- key = RandomGeneratorUtils.getRandomGenerator().pickone(this.rc4Keys);
- encodedValue = CryptUtils.btoa(CryptUtils.rc4(value, key));
- break;
- case StringArrayEncoding.base64:
- encodedValue = CryptUtils.btoa(value);
- break;
- default:
- encodedValue = value;
- }
- encodedValue = Utils.stringToUnicodeEscapeSequence(encodedValue, !this.options.unicodeEscapeSequence);
- return { encodedValue, key };
- }
- /**
- * @param value
- * @returns {string}
- */
- private replaceStringLiteralWithStringArrayCall (value: string): string {
- const { encodedValue, key }: IEncodedValue = this.getEncodedValue(value);
- const hexadecimalIndex: string = this.getArrayHexadecimalIndex(encodedValue);
- const rotatedStringArrayStorageId: string = Utils.stringRotate(this.stringArrayStorage.getStorageId(), 1);
- const stringArrayStorageCallsWrapperName: string = `_${Utils.hexadecimalPrefix}${rotatedStringArrayStorageId}`;
- if (key) {
- return `${stringArrayStorageCallsWrapperName}('${hexadecimalIndex}', '${Utils.stringToUnicodeEscapeSequence(key, !this.options.unicodeEscapeSequence)}')`;
- }
- return `${stringArrayStorageCallsWrapperName}('${hexadecimalIndex}')`;
- }
- }
|