const fs = require('fire-fs'); const path = require('fire-path'); const crypto = require('./libs/crypto'); const setting = require('./build-setting'); const utils = require('./libs/utils'); module.exports = (function (){ var _instance; function AssetsCrypto (params) { return { _ready: false, _files: [], _paths: [], _cipherKey: null, _cipherSign: null, init (actualPlatform) { this._ready = false; let assetsCrypto = `assetsCrypto`; let crypto = setting.getInstance().getItem(assetsCrypto); if (!crypto) { Editor.warn('缺少配置,跳过资源加密!'); return false; } if (!crypto.enable) { Editor.warn('未开启资源加密!'); return false; } let platform = crypto.platform || ''; // 平台配置 let supportList = platform.split(','); if (!supportList.includes(actualPlatform)) { Editor.warn(actualPlatform, '平台不支持资源加密'); return false; } let dir = crypto.dir; let key = crypto.key; let sign = crypto.sign; let exts = crypto.exts; let list = crypto.list; if (!dir || !key || !sign || !exts) { Editor.error('资源加密配置不满足'); return false; } this._dir = dir; this._cipherKey = key; // 用来加密的密钥key this._cipherSign = sign; // 签名用来标识加密图片 this._extList = exts.split(','); this._list = list || []; this._importUuids = []; for (const aPath of this._list) { let fullpath = path.join(Editor.Project.path, aPath); let stat = fs.statSync(fullpath); if (stat.isDirectory()) { utils.findFileSync(fullpath, (filePath)=> { this.addImportFile(filePath); }); } else { this.addImportFile(fullpath); } } this._ready = true; return true; }, addImportFile (filePath) { let index = filePath.lastIndexOf('.'); let ext = filePath.substr(index + 1); if (ext === 'DS_Store' || ext === 'meta') { return; } let uuid = Editor.assetdb._path2uuid[filePath]; this._importUuids.push(uuid); }, isReady () { return this._ready; }, getImportBuildUrl (root, uuid) { if (!root || !uuid) { return; } let dirname = uuid.substr(0, 2); let dirPath = path.join(root, 'res/import', dirname); let url = path.join(dirPath, uuid + '.json'); if (!fs.existsSync(url)) { if (!fs.existsSync(dirPath)) { return; } let dirs = fs.readdirSync(dirPath); for (const ele of dirs) { let fullpath = path.join(dirPath, ele); let stat = fs.statSync(fullpath); if (stat.isFile() && ele.includes(uuid)) { url = fullpath; break; } } } return url; }, addCryptoFile (filePath, isImport) { if (isImport) { this._files.push(filePath); return; } let index = filePath.lastIndexOf('.'); let ext = filePath.substr(index + 1); if (this._extList.includes(ext)) { this._files.push(filePath); } }, genFiles (buildDest) { this._files = []; for (const uuid of this._importUuids) { let fullpath = this.getImportBuildUrl(buildDest, uuid); if (fullpath) { this.addCryptoFile(fullpath); } } let rootPath = path.join(Editor.Project.path, this._dir); let stat = fs.statSync(rootPath); if (stat.isDirectory()) { utils.findFileSync(rootPath, (filePath)=> { this.addCryptoFile(filePath); }); } }, getFilesCount () { return this._files.length; }, encrypt (callback) { this._files.forEach((filePath, index) => { let data = fs.readFileSync(filePath); if (data) { let buffer = crypto.xor(data, this._cipherKey, this._cipherSign); if (buffer) { fs.writeFileSync(filePath, buffer); callback (filePath); } } else { Editor.error('读取' + filePath + '失败'); } }); }, decrypt (callback) { this._files.forEach((filePath, index) => { let data = fs.readFileSync(filePath); if (data) { let buffer = crypto.rox(data, this._cipherKey, this._cipherSign); if (buffer) { fs.writeFileSync(filePath, buffer); callback (filePath); } } else { Editor.error('读取' + filePath + '失败'); } }); }, modifyFileUtilsFile (buildDest) { // 需要被替换的值 let defSign = '{0x6a, 0x69, 0x61, 0x6d, 0x69}; // jiami'; let defKey = '7911ea3ff0ba6ea6d475da6418f254017911ea3ff0ba6ea6d475da6418f25401'; function strToHexCharCode (str) { var hexCharCode = '{'; for (var i = 0; i < str.length; i++) { hexCharCode += '0x' + (str.charCodeAt(i)).toString(16); if (i < (str.length - 1)) { hexCharCode += ', '; } } return hexCharCode + '}; // ' + str; } let cipherSign = strToHexCharCode(this._cipherSign); let filePath = buildDest + '/frameworks/cocos2d-x/cocos/platform/CCFileUtils.cpp'; if (fs.existsSync(filePath)) { let data = fs.readFileSync(filePath, 'utf-8'); if (data) { data = data.replace(defSign, cipherSign); data = data.replace(defKey, this._cipherKey); fs.writeFileSync(filePath, data, 'utf-8'); // 批量打包时时不存在这个路径的,也不需要处理 let packagePath = path.join(Editor.Project.path, '../mj-package-android/package/frameworks/cocos2d-x/cocos/platform/CCFileUtils.cpp'); if (fs.existsSync(packagePath)) { Editor.warn('修改UtilsFile.cpp中的签名:' + this._cipherSign + '密钥:' + this._cipherKey); fs.copyFileSync(filePath, packagePath); // 如果打包工程有temp_demo let packageTempPath = path.join(Editor.Project.path, '../mj-package-android/temp_demo/cocos2d-x/cocos/platform/CCFileUtils.cpp'); if (fs.existsSync(packageTempPath)) { fs.copyFileSync(filePath, packageTempPath); } } } else { Editor.error('读取' + filePath + '失败'); } } else { Editor.log('没有找到' + filePath + '文件'); } } }; } return { getInstance (params) { if (!_instance){ _instance = AssetsCrypto(params); } return _instance; } }; })();