tkyaji/cordova-plugin-crypt-file

How to remove '/+++/' in this path?

zhangzsan opened this issue · 5 comments

I need remove all '/+++/' code in this plugin,but when I removed all '/+++/' and used this plugin, app can not decrypt properly, anyone can answer?thanks

use

<content src="../index.html" />

in config.xml

but I'm having problems starting the app on the device.
the application cannot decrypt files that have been encrypted earlier. any solution?

Any Solution for this ??

Change on plugins>...>hooks>after_prepare.js

module.exports = function (context) {

    var path = require('path'),
        fs = require('fs'),
        crypto = require('crypto'),
        Q = require('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') {
            // modified path
            var pluginDir = path.join(platformPath, 'app/src/main/java');
            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;
                // 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');
    }
}