main.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. const Fs = require('fs');
  2. const Path = require('path');
  3. const JavascriptObfuscator = require('javascript-obfuscator');
  4. const configFileDir = 'local/';
  5. const configFileName = 'ccc-obfuscated-code.json';
  6. const defaultConfig = {
  7. auto: false,
  8. // extraFiles: [],
  9. // useAbsPath: false,
  10. preset: 'lower',
  11. options: {}
  12. };
  13. const presetFileUrl = 'packages://ccc-obfuscated-code/preset.json';
  14. let presets = null;
  15. module.exports = {
  16. load() {
  17. Editor.Builder.on('build-start', this.onBuildStart);
  18. Editor.Builder.on('before-change-files', this.onBeforeChangeFiles);
  19. },
  20. unload() {
  21. Editor.Builder.removeListener('build-start', this.onBuildStart);
  22. Editor.Builder.removeListener('before-change-files', this.onBeforeChangeFiles);
  23. },
  24. messages: {
  25. 'open-panel'() {
  26. Editor.Panel.open('ccc-obfuscated-code');
  27. },
  28. // TODO
  29. // 'open-panel-do'() {
  30. // Editor.Panel.open('ccc-obfuscated-code-do');
  31. // },
  32. 'save-config'(event, config) {
  33. const configFilePath = saveConfig(config);
  34. Editor.log('[CC]', '保存配置', configFilePath);
  35. event.reply(null, true);
  36. },
  37. 'read-config'(event) {
  38. const config = getConfig();
  39. if (config) Editor.log('[CC]', '读取本地配置');
  40. else Editor.log('[CC]', '未找到本地配置文件');
  41. event.reply(null, config);
  42. },
  43. 'get-preset'(event, name) {
  44. Editor.log('[CC]', '读取预设', name);
  45. let preset = getPreset(name);
  46. if (preset) {
  47. event.reply(null, preset);
  48. } else {
  49. Editor.warn('[CC]', '预设文件已丢失');
  50. Editor.warn('[CC]', '预设文件下载地址 https://gitee.com/ifaswind/ccc-obfuscated-code/blob/master/preset.json');
  51. event.reply(null, {});
  52. }
  53. }
  54. },
  55. /**
  56. *
  57. * @param {BuildOptions} options
  58. * @param {Function} callback
  59. */
  60. onBuildStart(options, callback) {
  61. const config = getConfig();
  62. if (config.auto) Editor.log('[CC]', '将在项目构建完成后自动混淆代码');
  63. callback();
  64. },
  65. /**
  66. *
  67. * @param {BuildOptions} options
  68. * @param {Function} callback
  69. */
  70. onBeforeChangeFiles(options, callback) {
  71. const config = getConfig();
  72. if (config.auto) {
  73. Editor.log('[CC]', '正在混淆代码');
  74. // Cocos Creator 2.4 以下
  75. const srcPath = Path.join(options.dest, 'src', 'project.js');
  76. if (Fs.existsSync(srcPath)) {
  77. obfuscate(srcPath, config.options);
  78. Editor.log('[CC]', '已混淆代码文件', srcPath);
  79. }
  80. // Cocos Creator 2.4 以上
  81. const list = ['assets', 'subpackages'];
  82. for (let i = 0; i < list.length; i++) {
  83. const dirPath = Path.join(options.dest, list[i]);
  84. if (!Fs.existsSync(dirPath)) continue;
  85. const names = Fs.readdirSync(dirPath);
  86. for (const name of names) {
  87. if (list[i] === 'assets' && (name === 'internal' || name === 'resources')) continue;
  88. const filePath = Path.join(dirPath, name, 'index.js');
  89. if (Fs.existsSync(filePath)) {
  90. obfuscate(filePath, config.options);
  91. Editor.log('[CC]', '已混淆代码文件', filePath);
  92. }
  93. }
  94. }
  95. // 额外需要混淆的文件
  96. // for (let i = 0; i < config.extraFiles.length; i++) {
  97. // if (config.extraFiles[i] === '') continue;
  98. // const path = config.useAbsPath ? config.extraFiles[i] : Path.join(options.dest, config.extraFiles[i]);
  99. // if (Fs.existsSync(path)) {
  100. // obfuscate(path, config.options);
  101. // Editor.log('[CC]', '已额外混淆文件', path);
  102. // } else {
  103. // Editor.warn('[CC]', '需额外混淆文件不存在', path);
  104. // }
  105. // }
  106. Editor.log('[CC]', '混淆已完成');
  107. }
  108. callback();
  109. },
  110. }
  111. /**
  112. * 保存配置
  113. * @param {object} config
  114. */
  115. function saveConfig(config) {
  116. // 查找目录
  117. const projectPath = Editor.Project.path || Editor.projectPath;
  118. const configDirPath = Path.join(projectPath, configFileDir);
  119. if (!Fs.existsSync(configDirPath)) Fs.mkdirSync(configDirPath);
  120. const configFilePath = Path.join(projectPath, configFileDir, configFileName);
  121. // 读取本地配置
  122. let object = {};
  123. if (Fs.existsSync(configFilePath)) {
  124. object = JSON.parse(Fs.readFileSync(configFilePath, 'utf8'));
  125. }
  126. // 写入配置
  127. for (const key in config) { object[key] = config[key]; }
  128. Fs.writeFileSync(configFilePath, JSON.stringify(object, null, 2));
  129. return configFilePath;
  130. }
  131. /**
  132. * 读取配置
  133. */
  134. function getConfig() {
  135. const projectPath = Editor.Project.path || Editor.projectPath;
  136. const configFilePath = Path.join(projectPath, configFileDir, configFileName);
  137. let config = null;
  138. if (Fs.existsSync(configFilePath)) {
  139. config = JSON.parse(Fs.readFileSync(configFilePath, 'utf8'));
  140. }
  141. if (!config) {
  142. config = JSON.parse(JSON.stringify(defaultConfig));
  143. config.options = getPreset('off');
  144. if (config.preset !== 'off') {
  145. const preset = getPreset(config.preset);
  146. for (const key in preset) { config.options[key] = preset[key]; }
  147. }
  148. }
  149. return config;
  150. }
  151. /**
  152. * 读取预设参数
  153. * @param {string} type 预设名
  154. */
  155. function getPreset(type) {
  156. if (presets) return presets[type];
  157. const presetFilePath = Editor.url(presetFileUrl);
  158. if (Fs.existsSync(presetFilePath)) {
  159. presets = JSON.parse(Fs.readFileSync(presetFilePath, 'utf8'));
  160. return presets[type];
  161. }
  162. return null;
  163. }
  164. /**
  165. * 混淆
  166. * @param {string} filePath 文件路径
  167. * @param {ObfuscatorOptions} options 混淆参数
  168. */
  169. function obfuscate(filePath, options) {
  170. const sourceCode = Fs.readFileSync(filePath, 'utf8');
  171. const obfuscationResult = JavascriptObfuscator.obfuscate(sourceCode, options);
  172. const obfuscatedCode = obfuscationResult.getObfuscatedCode();
  173. Fs.writeFileSync(filePath, obfuscatedCode);
  174. }