JavaScriptObfuscatorCLI.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import * as path from 'path';
  2. import { Command } from 'commander';
  3. import { IObfuscationResult } from "../interfaces/IObfuscationResult";
  4. import { IOptionsPreset } from "../interfaces/IOptionsPreset";
  5. import { SourceMapMode } from "../enums/SourceMapMode";
  6. import { DEFAULT_PRESET } from "../preset-options/DefaultPreset";
  7. import { CLIUtils } from "./CLIUtils";
  8. import { JavaScriptObfuscator } from "../JavaScriptObfuscator";
  9. import { JavaScriptObfuscatorInternal } from "../JavaScriptObfuscatorInternal";
  10. import { Utils } from "../Utils";
  11. export class JavaScriptObfuscatorCLI {
  12. /**
  13. * @type {string[]}
  14. */
  15. private arguments: string[];
  16. /**
  17. * @type {commander.ICommand}
  18. */
  19. private commands: commander.ICommand;
  20. /**
  21. * @type {string}
  22. */
  23. private data: string = '';
  24. /**
  25. * @type {string}
  26. */
  27. private inputPath: string;
  28. /**
  29. * @type {string[]}
  30. */
  31. private rawArguments: string[];
  32. /**
  33. * @param argv
  34. */
  35. constructor (argv: string[]) {
  36. this.rawArguments = argv;
  37. this.arguments = this.rawArguments.slice(2);
  38. }
  39. /**
  40. * @returns {string}
  41. */
  42. private static getBuildVersion (): string {
  43. return CLIUtils.getPackageConfig().version;
  44. }
  45. /**
  46. * @param value
  47. * @returns {boolean}
  48. */
  49. private static parseBoolean (value: string): boolean {
  50. return value === 'true' || value === '1';
  51. }
  52. /**
  53. * @param value
  54. * @returns {string}
  55. */
  56. private static parseSourceMapMode (value: string): string {
  57. let availableMode: boolean = Object
  58. .keys(SourceMapMode)
  59. .some((key: string): boolean => {
  60. return SourceMapMode[key] === value;
  61. });
  62. if (!availableMode) {
  63. throw new ReferenceError('Invalid value of `--sourceMapMode` option');
  64. }
  65. return value;
  66. }
  67. public run (): void {
  68. this.configureCommands();
  69. if (!this.arguments.length || Utils.arrayContains(this.arguments, '--help')) {
  70. this.commands.outputHelp();
  71. return;
  72. }
  73. this.inputPath = CLIUtils.getInputPath(this.arguments);
  74. this.getData();
  75. this.processData();
  76. }
  77. /**
  78. * @returns {IOptionsPreset}
  79. */
  80. private buildOptions (): IOptionsPreset {
  81. let options: IOptionsPreset = {},
  82. availableOptions: string[] = Object.keys(DEFAULT_PRESET);
  83. for (let option in this.commands) {
  84. if (!this.commands.hasOwnProperty(option)) {
  85. continue;
  86. }
  87. if (!Utils.arrayContains(availableOptions, option)) {
  88. continue;
  89. }
  90. options[option] = (<any>this.commands)[option];
  91. }
  92. return Object.assign({}, DEFAULT_PRESET, options);
  93. }
  94. private configureCommands (): void {
  95. this.commands = new Command()
  96. .version(JavaScriptObfuscatorCLI.getBuildVersion(), '-v, --version')
  97. .usage('<inputPath> [options]')
  98. .option('-o, --output <path>', 'Output path for obfuscated code')
  99. .option('--compact <boolean>', 'Disable one line output code compacting', JavaScriptObfuscatorCLI.parseBoolean)
  100. .option('--debugProtection <boolean>', 'Disable browser Debug panel (can cause DevTools enabled browser freeze)', JavaScriptObfuscatorCLI.parseBoolean)
  101. .option('--debugProtectionInterval <boolean>', 'Disable browser Debug panel even after page was loaded (can cause DevTools enabled browser freeze)', JavaScriptObfuscatorCLI.parseBoolean)
  102. .option('--disableConsoleOutput <boolean>', 'Allow console.log, console.info, console.error and console.warn messages output into browser console', JavaScriptObfuscatorCLI.parseBoolean)
  103. .option('--encodeUnicodeLiterals <boolean>', 'All literals in Unicode array become encoded in Base64 (this option can slightly slow down your code speed)', JavaScriptObfuscatorCLI.parseBoolean)
  104. .option('--reservedNames <list>', 'Disable obfuscation of variable names, function names and names of function parameters that match the passed RegExp patterns (comma separated)', (val: string) => val.split(','))
  105. .option('--rotateUnicodeArray <boolean>', 'Disable rotation of unicode array values during obfuscation', JavaScriptObfuscatorCLI.parseBoolean)
  106. .option('--selfDefending <boolean>', 'Disables self-defending for obfuscated code', JavaScriptObfuscatorCLI.parseBoolean)
  107. .option('--sourceMap <boolean>', 'Enables source map generation', JavaScriptObfuscatorCLI.parseBoolean)
  108. .option(
  109. '--sourceMapMode <string> [inline, separate]',
  110. 'Specify source map output mode',
  111. JavaScriptObfuscatorCLI.parseSourceMapMode
  112. )
  113. .option('--unicodeArray <boolean>', 'Disables gathering of all literal strings into an array and replacing every literal string with an array call', JavaScriptObfuscatorCLI.parseBoolean)
  114. .option('--unicodeArrayThreshold <number>', 'The probability that the literal string will be inserted into unicodeArray (Default: 0.8, Min: 0, Max: 1)', parseFloat)
  115. .option('--wrapUnicodeArrayCalls <boolean>', 'Disables usage of special access function instead of direct array call', JavaScriptObfuscatorCLI.parseBoolean)
  116. .parse(this.rawArguments);
  117. this.commands.on('--help', () => {
  118. console.log(' Examples:\n');
  119. console.log(' %> javascript-obfuscator in.js --compact true --selfDefending false');
  120. console.log(' %> javascript-obfuscator in.js --output out.js --compact true --selfDefending false');
  121. console.log('');
  122. });
  123. }
  124. private getData (): void {
  125. this.data = CLIUtils.readFile(this.inputPath);
  126. }
  127. private processData (): void {
  128. let options: IOptionsPreset = this.buildOptions(),
  129. outputCodePath: string = CLIUtils.getOutputCodePath(this.commands, this.inputPath);
  130. if (options.sourceMap) {
  131. this.processDataWithSourceMap(outputCodePath, options);
  132. } else {
  133. this.processDataWithoutSourceMap(outputCodePath, options);
  134. }
  135. }
  136. /**
  137. * @param outputCodePath
  138. * @param options
  139. */
  140. private processDataWithoutSourceMap (outputCodePath: string, options: IOptionsPreset): void {
  141. let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.data, options);
  142. CLIUtils.writeFile(outputCodePath, obfuscatedCode);
  143. }
  144. /**
  145. * @param outputCodePath
  146. * @param options
  147. */
  148. private processDataWithSourceMap (outputCodePath: string, options: IOptionsPreset): void {
  149. let javaScriptObfuscator: JavaScriptObfuscatorInternal = new JavaScriptObfuscatorInternal(this.data, options),
  150. obfuscationResult: IObfuscationResult,
  151. outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(outputCodePath);
  152. javaScriptObfuscator.obfuscate();
  153. if (options.sourceMapMode === SourceMapMode.Separate) {
  154. javaScriptObfuscator.setSourceMapUrl(
  155. path.basename(outputSourceMapPath)
  156. );
  157. }
  158. obfuscationResult = javaScriptObfuscator.getObfuscationResult();
  159. CLIUtils.writeFile(outputCodePath, obfuscationResult.obfuscatedCode);
  160. if (obfuscationResult.sourceMap) {
  161. CLIUtils.writeFile(outputSourceMapPath, obfuscationResult.sourceMap);
  162. }
  163. }
  164. }