UNPKG

cordova-plugin-crypt-file

Version:
170 lines (136 loc) 7.74 kB
module.exports = function(context) { var path = context.requireCordovaModule('path'), fs = context.requireCordovaModule('fs'), crypto = context.requireCordovaModule('crypto'), Q = context.requireCordovaModule('q'), cordova_util = context.requireCordovaModule('cordova-lib/src/cordova/util'), platforms = context.requireCordovaModule('cordova-lib/src/platforms/platforms'), Parser = context.requireCordovaModule('cordova-lib/src/cordova/metadata/parser'), ParserHelper = context.requireCordovaModule('cordova-lib/src/cordova/metadata/parserhelper/ParserHelper'), ConfigParser = context.requireCordovaModule('cordova-common').ConfigParser; var deferral = new Q.defer(); var projectRoot = cordova_util.cdProjectRoot(); var key = crypto.randomBytes(24).toString('base64'); var iv = crypto.randomBytes(12).toString('base64'); console.log('key=' + key + ', iv=' + iv) var targetFiles = loadCryptFileTargets(); context.opts.platforms.filter(function(platform) { var pluginInfo = context.opts.plugin.pluginInfo; return pluginInfo.getPlatformsArray().indexOf(platform) > -1; }).forEach(function(platform) { var platformPath = path.join(projectRoot, 'platforms', platform); var platformApi = platforms.getPlatformApi(platform, platformPath); var platformInfo = platformApi.getPlatformInfo(); var wwwDir = platformInfo.locations.www; findCryptFiles(wwwDir).filter(function(file) { return isCryptFile(file.replace(wwwDir, '')); }).forEach(function(file) { var content = fs.readFileSync(file, 'utf-8'); fs.writeFileSync(file, encryptData(content, key, iv), 'utf-8'); console.log('encrypt: ' + file); }); if (platform == 'ios') { var pluginDir; try { var ios_parser = context.requireCordovaModule('cordova-lib/src/cordova/metadata/ios_parser'), iosParser = new ios_parser(platformPath); pluginDir = path.join(iosParser.cordovaproj, 'Plugins', context.opts.plugin.id); } catch (err) { var xcodeproj_dir = fs.readdirSync(platformPath).filter(function(e) { return e.match(/\.xcodeproj$/i); })[0], xcodeproj = path.join(platformPath, xcodeproj_dir), originalName = xcodeproj.substring(xcodeproj.lastIndexOf(path.sep)+1, xcodeproj.indexOf('.xcodeproj')), cordovaproj = path.join(platformPath, originalName); pluginDir = path.join(cordovaproj, 'Plugins', context.opts.plugin.id); } replaceCryptKey_ios(pluginDir, key, iv); } else if (platform == 'android') { var pluginDir = path.join(platformPath, 'src'); replaceCryptKey_android(pluginDir, key, iv); var cfg = new ConfigParser(platformInfo.projectConfig.path); cfg.doc.getroot().getchildren().filter(function(child, idx, arr) { return (child.tag == 'content'); }).forEach(function(child) { child.attrib.src = '/+++/' + child.attrib.src; }); cfg.write(); } }); deferral.resolve(); return deferral.promise; function findCryptFiles(dir) { var fileList = []; var list = fs.readdirSync(dir); list.forEach(function(file) { fileList.push(path.join(dir, file)); }); // sub dir list.filter(function(file) { return fs.statSync(path.join(dir, file)).isDirectory(); }).forEach(function(file) { var subDir = path.join(dir, file) var subFileList = findCryptFiles(subDir); fileList = fileList.concat(subFileList); }); return fileList; } function loadCryptFileTargets() { var xmlHelpers = context.requireCordovaModule('cordova-common').xmlHelpers; var pluginXml = path.join(context.opts.plugin.dir, 'plugin.xml'); var include = []; var exclude = []; var doc = xmlHelpers.parseElementtreeSync(pluginXml); var cryptfiles = doc.findall('cryptfiles'); if (cryptfiles.length > 0) { cryptfiles[0]._children.forEach(function(elm) { elm._children.filter(function(celm) { return celm.tag == 'file' && celm.attrib.regex && celm.attrib.regex.trim().length > 0; }).forEach(function(celm) { if (elm.tag == 'include') { include.push(celm.attrib.regex.trim()); } else if (elm.tag == 'exclude') { exclude.push(celm.attrib.regex.trim()); } }); }) } return {'include': include, 'exclude': exclude}; } function isCryptFile(file) { if (!targetFiles.include.some(function(regexStr) { return new RegExp(regexStr).test(file); })) { return false; } if (targetFiles.exclude.some(function(regexStr) { return new RegExp(regexStr).test(file); })) { return false; } return true; } function encryptData(input, key, iv) { var cipher = crypto.createCipheriv('aes-256-cbc', key, iv); var encrypted = cipher.update(input, 'utf8', 'base64') + cipher.final('base64'); return encrypted; } function replaceCryptKey_ios(pluginDir, key, iv) { var sourceFile = path.join(pluginDir, 'CDVCryptURLProtocol.m'); var content = fs.readFileSync(sourceFile, 'utf-8'); var includeArrStr = targetFiles.include.map(function(pattern) { return '@"' + pattern.replace('\\', '\\\\') + '"'; }).join(', '); var excludeArrStr = targetFiles.exclude.map(function(pattern) { return '@"' + pattern.replace('\\', '\\\\') + '"'; }).join(', '); content = content.replace(/kCryptKey = @".*";/, 'kCryptKey = @"' + key + '";') .replace(/kCryptIv = @".*";/, 'kCryptIv = @"' + iv + '";') .replace(/kIncludeFiles\[\] = {.*};/, 'kIncludeFiles\[\] = { ' + includeArrStr + ' };') .replace(/kExcludeFiles\[\] = {.*};/, 'kExcludeFiles\[\] = { ' + excludeArrStr + ' };') .replace(/kIncludeFileLength = [0-9]+;/, 'kIncludeFileLength = ' + targetFiles.include.length + ';') .replace(/kExcludeFileLength = [0-9]+;/, 'kExcludeFileLength = ' + targetFiles.exclude.length + ';'); fs.writeFileSync(sourceFile, content, 'utf-8'); } function replaceCryptKey_android(pluginDir, key, iv) { var sourceFile = path.join(pluginDir, 'com/tkyaji/cordova/DecryptResource.java'); var content = fs.readFileSync(sourceFile, 'utf-8'); var includeArrStr = targetFiles.include.map(function(pattern) { return '"' + pattern.replace('\\', '\\\\') + '"'; }).join(', '); var excludeArrStr = targetFiles.exclude.map(function(pattern) { return '"' + pattern.replace('\\', '\\\\') + '"'; }).join(', '); content = content.replace(/CRYPT_KEY = ".*";/, 'CRYPT_KEY = "' + key + '";') .replace(/CRYPT_IV = ".*";/, 'CRYPT_IV = "' + iv + '";') .replace(/INCLUDE_FILES = new String\[\] {.*};/, 'INCLUDE_FILES = new String[] { ' + includeArrStr + ' };') .replace(/EXCLUDE_FILES = new String\[\] {.*};/, 'EXCLUDE_FILES = new String[] { ' + excludeArrStr + ' };'); fs.writeFileSync(sourceFile, content, 'utf-8'); } }