tkyaji / cordova-plugin-crypt-file

This plugin to encrypt the source files.
Apache License 2.0
178 stars 116 forks source link

Using "requireCordovaModule" to load non-cordova module "path" is not supported. Instead, add this module to your dependencies and use regular "require" to load it. #99

Open inclusiveFuture opened 2 years ago

inclusiveFuture commented 2 years ago

When building/running, the error gives:

Using "requireCordovaModule" to load non-cordova module "path" is not supported. Instead, add this module to your dependencies and use regular "require" to load it.

cordova 10.0.0, cordova-lib@10.1.0 ├── cordova-android@9.1.0 ├── cordova-ios@6.2.0 ├── cordova-plugin-crypt-file@1.3.3 └── cordova-plugin-whitelist@1.3.5

breelig commented 2 years ago

I'm having the same problem.

cordova 11.0.0, cordova-lib@11.0.0 ├── cordova-android@10.1.0 ├── cordova-ios@6.2.0 ├── cordova-plugin-crypt-file@1.3.3

taufiksu commented 2 years ago

I'm modified plugins>..>hooks>after_prepare.js to disable some require variable and change android plugin path for cordova 11.0.0 and it work.

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');
    }
}
ydarwin commented 1 year ago

Some official answer?