diff --git a/scripts/aes.js b/scripts/aes.js new file mode 100644 index 0000000..e8b138f --- /dev/null +++ b/scripts/aes.js @@ -0,0 +1,9 @@ +#! /usr/bin/env runjs +var AESCrypt = Packages.me.hatter.tools.commons.security.crypt.AESCrypt; + +var main = () => { + AESCrypt.main($ARGS); +}; + +main(); + diff --git a/scripts/async.js b/scripts/async.js new file mode 100644 index 0000000..6a7fb5f --- /dev/null +++ b/scripts/async.js @@ -0,0 +1,105 @@ +#! /usr/bin/env runjs + +var Thread = java.lang.Thread; +var Runtime = java.lang.Runtime; + +var argsjs = require('component-args.js'); +var jsonjs = require('component-json-ex.js'); + +var printHelp = () => { + println('async.js [options] '); + println(); + println('-h, --help Print help'); + println('-i, --interval Time every refresh, default 1 (s)'); + println('-t, --token Token, default read from ~/.jssp/config/asyncjs.token'); + return; +}; + +var main = () => { + var args = argsjs.parseDefARGs(['h', 'help']); + if (args.flg('h', 'help')) { + printHelp(); + return; + } + if (args.length < 1) { + xprintln('[ERROR] Target id and filename is not assigned.'); + printHelp(); + return; + } + var id = args[0]; + + var interval = args.val('i', 'interfal') || 1; + var token = args.val('t', 'token'); + if (token == null) { + var tokenFile = $$.file('~/.jssp/config/asyncjs.token'); + if (tokenFile.exists()) { token = $$.rFile(tokenFile).string().trim(); } + } + if (token == null) { + xprintln('[ERROR] Token is not assigned!'); + return; + } + + var getResultStr = $$.httpRequest().url('https://playsecurity.org/editItem.jsonp').post($$.keyValues() + .kv('token', token) + .kv('id', id) + .kv('act', 'GET') + .join()).toString(); + var getResultJSON = JSON.parse(getResultStr); + + if (getResultJSON.status != 200) { + xprintln('[ERROR] Get item failed: ' + getResultStr); + return; + } + + var fn = getResultJSON.data.fileName; + var body = getResultJSON.data.body; + + var localFile = $$.file(id + '_' + fn); + if (localFile.exists()) { + xprintln('[ERROR] File exists: ' + localFile); + return; + } + + $$.rFile(localFile).write(body); + xprintln('[OK] Write file success: ' + localFile); + + Runtime.getRuntime().addShutdownHook(new Thread(() => { + xprintln('[INFO] Watch ended: ' + localFile); + })); + + var localFileLastModifiled = localFile.lastModified(); + xprintln('[INFO] Last modified: ' + localFileLastModifiled); + xprintln('[INFO] Watching thread is running...'); + + while (true) { + $$.sleep(500); + var modified = localFile.lastModified(); + if (modified > localFileLastModifiled) { + var now = $$.date().millis(); + if ((now - modified) < 100) { $$.sleep(100); } + + var secs = '' + $$.num(modified).sub(localFileLastModifiled).divr(1000, 0, null); + xprintln('[INFO] File last modified updated: ' + + localFileLastModifiled + ' -> ' + modified + + ', diff: ' + + repeat(' ', (6 - secs.length)) + secs + ' s'); + + var putResultStr = $$.httpRequest().url('https://playsecurity.org/editItem.jsonp').post($$.keyValues() + .kv('token', token) + .kv('id', id) + .kv('act', 'PUT') + .kv('body', $$.rFile(localFile).string()) + .join()).toString(); + var putResultJSON = JSON.parse(putResultStr); + + if (getResultJSON.status != 200) { + xprintln('[ERROR] Put item failed: ' + getResultStr); // STOP ? + } else { + xprintln('[OK] Put item successed!') + } + localFileLastModifiled = modified; + } + } +}; + +main(); diff --git a/scripts/base58.js b/scripts/base58.js new file mode 100644 index 0000000..4b43391 --- /dev/null +++ b/scripts/base58.js @@ -0,0 +1,9 @@ +#! /usr/bin/env runjs +var Base58Tool = Packages.me.hatter.tools.commons.tool.Base58Tool; + +var main = () => { + Base58Tool.main($ARGS); +}; + +main(); + diff --git a/scripts/build-util.js b/scripts/build-util.js new file mode 100644 index 0000000..c776c9c --- /dev/null +++ b/scripts/build-util.js @@ -0,0 +1,250 @@ +#! /usr/bin/env runjs + +var argsEx = require('component-args.js'); +var jsonEx = require('component-json-ex.js'); + +var System = java.lang.System; +var OSUtil = Packages.me.hatter.tools.commons.os.OSUtil; + +var jdkPackageBaseURL = 'http://publicbucket-1251781687.coscd.myqcloud.com/'; +var jdkPackages = [ + { + 'jdk': 'jdk-7u80-linux-x64.tar.gz', + 'sha256': 'bad9a731639655118740bee119139c1ed019737ec802a630dd7ad7aab4309623' + }, { + 'jdk': 'jdk-8u121-linux-x64.tar.gz', + 'sha256': '97e30203f1aef324a07c94d9d078f5d19bb6c50e638e4492722debca588210bc' + }, { + 'jdk': 'jdk-9.0.4_linux-x64_bin.tar.gz', + 'sha256': '90c4ea877e816e3440862cfa36341bc87d05373d53389ec0f2d54d4e8c95daa2' + } +]; + +var printHelp = () => { + println('build-util.js '); + println(); + println('-h, --help Print help'); + println(' --init Init build.json'); + println(' --init-java Init Java config'); + println(' --list List Java versions'); + println(' --list-jdks List JDK packages'); + return; +}; + +var initBuildJSON = () => { + var buildGradle = $$.file('build.gradle'); + var buildJSON = $$.file('build.json'); + + if ((buildGradle.exists()) && (buildJSON.exists())) { + xprintln('[ERROR] File build.gradle and build.json exists.'); + } + + print('Input project name: '); + var projectName = System.console().readLine(); + if (!(projectName)) { + xprintln('[ERROR] Project name cannot be empty.'); + return; + } + + print('Select Java(1.6, 1.7, 1.8, 9.0, default 1.8): '); + var javaVersion = System.console().readLine(); + javaVersion = $STR(javaVersion || '1.8'); + if (!(['1.6', '1.7', '1.8', '9.0'].contains(javaVersion))) { + xprintln('[ERROR] Unknow java version: ' + javaVersion); + return; + } + + print('Select Builder(ant, gradle, maven, default gradle): '); + var builder = System.console().readLine(); + builder = $STR(builder || 'gradle'); + if (!(['ant', 'gradle', 'maven'].contains(builder))) { + xprintln('[ERROR] Unknow builder: ' + builder); + return; + } + + var builderVersion; + if ($STR(builder) == 'ant') { + builderVersion = '1.7'; + } else if ($STR(builder) == 'maven') { + print('Select Maven(2.2.1, 3.5.2, default 3.5.2): '); + builderVersion = System.console().readLine(); + builderVersion = $STR(builderVersion || '3.5.2'); + if (!(['2.2.1', '3.5.2'].contains(builderVersion))) { + xprintln('[ERROR] Unknow builder version: ' + builderVersion); + return; + } + } else { + print('Select Gradle(1.0, 3.1, default 3.1): '); + builderVersion = System.console().readLine(); + builderVersion = $STR(builderVersion || '3.1'); + if (!(['1.0', '3.1'].contains(builderVersion))) { + xprintln('[ERROR] Unknow builder version: ' + builderVersion); + return; + } + } + + println('[INFO] Name : ' + projectName); + println('[INFO] Java : ' + javaVersion); + println('[INFO] Builder : ' + builder + '/' + builderVersion); + + if ($STR(builder) == 'ant') { + xprintln('[ERROR] Ant currently is not supported!!!'); + return; + } + + if (($STR(builder) == 'gradle') && (!(buildGradle.exists()))) { + xprintln('[INFO] Create file: ' + buildGradle.getName()); + var buildGradleContent = $$.httpRequest().skipCertCheck().url('https://repo.examp1e.org/attachment/build.gradle').get().string(); + buildGradleContent = buildGradleContent.replace('//BASE_PROJECT_NAME//', projectName); + buildGradleContent = buildGradleContent.replace('//SOURCE_COMPATIBILITY//', javaVersion); + buildGradleContent = buildGradleContent.replace('//TARGET_COMPATIBILITY//', javaVersion); + buildGradleContent = buildGradleContent.replace('//JAVA_COMPILE//', ((builderVersion == '1.0') ? 'Compile' : 'JavaCompile')); + + print('Use maven repo(Y/N)? '); + var useMavenRepo = System.console().readLine(); + if ($STR(useMavenRepo).toLowerCase() == 'y') { + buildGradleContent = buildGradleContent.replace(/\/\/DISABLE_MVN_REPO\/\/ /g, ''); + } + + $$.rFile(buildGradle).write(buildGradleContent); + } + if (!(buildJSON.exists())) { + xprintln('[INFO] Create file: ' + buildJSON.getName()); + var bJSON = { + 'java': javaVersion, + 'builder': { + 'name': builder, + 'version': builderVersion + } + }; + $$.rFile(buildJSON).write(jsonEx.prettyJSON(bJSON)); + } + + if (($STR(builder) == 'gradle')) { + print('Need init app(Y/N)? '); + var initApp = System.console().readLine(); + if ($STR(initApp).toLowerCase() == 'y') { + $$.shell().inheritIO().commands('runjs', '-u', 'https://repo.examp1e.org/app/build.js', 'initapp').run(); + } + } + + if ($$.file('src').exists()) { + print('Need init eclipse(Y/N)? ') + var initEclipse = System.console().readLine(); + if ($STR(initEclipse).toLowerCase() == 'y') { + if (($STR(builder) == 'gradle') && $$.file('build.gradle').exists()) { + $$.shell().inheritIO().commands('runjs', '-u', 'https://repo.examp1e.org/app/build.js', 'eclipse').run(); + } + if (($STR(builder) == 'maven') && $$.file('pom.xml').exists()) { + $$.shell().inheritIO().commands('runjs', '-u', 'https://repo.examp1e.org/app/build.js', 'eclipse:eclipse').run(); + } + } + } + + var gitignore = $$.file('.gitignore'); + if (!(gitignore.exists())) { + print('Need create .gitignore(Y/N)? ') + var createGitIgnore = System.console().readLine(); + if ($STR(createGitIgnore).toLowerCase() == 'y') { + var defaultGitIgnore = [ + 'build', + 'classes', + '.DS_Store', + '.gradle', + '.classpath', + '.project', + '.settings' + ]; + $$.rFile(gitignore).write(defaultGitIgnore.join('\n')); + } + } + + xprintln('[SUCCESS] Done!'); +}; + +var getBuildConfigJSON = () => { + return $$.file('~', '.jssp', 'config', 'buildconfig.json'); +}; + +var getCurrentJavaHome = () => { + var javaHome = $$.prop('java.home'); + var javaHomeFile = $$.file(javaHome); + if ($STR(javaHomeFile.getName()) == 'jre') { + if ($$.file(javaHomeFile.getParentFile(), 'bin', 'java').exists()) { + javaHome = javaHomeFile.getParentFile().getAbsolutePath(); + } + } + return javaHome; +}; + +var initJavaVersion = () => { + var javaVersion = $$.prop('java.version'); + var javaHome = getCurrentJavaHome(); + var buildConfig = getBuildConfigJSON(); + var buildConfigJSON = JSON.parse((buildConfig.exists() && $$.rFile(buildConfig).string()) || '{}'); + if (buildConfigJSON['java'] && buildConfigJSON['java'][javaVersion]) { + xprintln('[WARN] Java config exists.'); + xprintln('[INFO] Configed JAVA_HOME path: ' + buildConfigJSON['java'][javaVersion]['home']); + return; + } + println('[INFO] Current Java version : ' + javaVersion); + println('[INFO] Current JAVA_HOME : ' + javaHome); + print('Add Current Java to build config(Y/N)?'); + var addJava = System.console().readLine(); + if ($STR(addJava).toLowerCase() == 'y') { + buildConfigJSON['java'] = buildConfigJSON['java'] || {}; + buildConfigJSON['java'][javaVersion] = buildConfigJSON['java'][javaVersion] || {}; + buildConfigJSON['java'][javaVersion]['home'] = javaHome; + buildConfigJSON['java']['versions'] = buildConfigJSON['java']['versions'] || []; + buildConfigJSON['java']['versions'].push(javaVersion); + + $$.rFile(buildConfig).write(jsonEx.prettyJSON(buildConfigJSON)); + } +}; + +var main = () => { + var args = argsEx.parseARGS(['h', 'help', 'init', 'init-java', 'list', 'list-jdks']); + + if (args.flags.flg('init')) { + initBuildJSON(); + } else if (args.flags.flg('init-java')) { + if (OSUtil.isMacOS()) { + xprintln('[WARN] macOS DO NOT need init java, build.js will use /usr/libexec/java_home.'); + } else { + initJavaVersion(); + } + } else if (args.flags.flg('list-jdks')) { + println('Dowload base URL: ' + jdkPackageBaseURL); + jdkPackages.forEach((jdk) => { + println(' ' + jdk.jdk + repeat(' ', (30 - jdk.jdk.length)) + ' - ' + jdk.sha256); + }); + } else if (args.flags.flg('list')) { + if (OSUtil.isMacOS()) { + $$.shell().inheritIO().commands('/usr/libexec/java_home', '-V').run(); + } else { + var buildConfig = getBuildConfigJSON(); + if (!(buildConfig.exists())) { + xprintln('[ERROR] build config file not found.'); + return; + } + var buildConfigJSON = JSON.parse($$.rFile(buildConfig).string()); + if (buildConfigJSON['java'] && buildConfigJSON['java']['versions']) { + var versions = buildConfigJSON['java']['versions'].sort(); + println('Matching Java Virtual Machines (' + versions.length + '):'); + versions.forEach((v) => { + println(' ' + v + ': ' + buildConfigJSON['java'][v]['home']); + }); + } + println(); + println(getCurrentJavaHome()); + } + } else { + if (!(args.flags.flg('h', 'help'))) { + xprintln('[ERROR] Args error!'); + println(); + } + printHelp(); + } +}; + +main(); diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 0000000..d16f05e --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,260 @@ +#!/usr/bin/env runjs + +var Integrity = Packages.me.hatter.tools.commons.security.digest.Integrity; + +var counter = require('component-counter.js'); +var javahomejs = require('component-javahome.js'); +var colorprint = require('component-colorprint-ex.js'); + +var doGetPackage = (name, bin, version) => { + var gradleHome = '~/.jssp/builder/' + name + '-' + version; + var gradleInfoRFile = __.rfile.from(gradleHome).file('info.json'); + if (gradleInfoRFile.exists()) { + return gradleInfoRFile.parseJSON(); + } + if (__.rfile.from(gradleHome).notExists()) { __.rfile.from(gradleHome).file().mkdirs(); } + + var toolPackageDetail = $$.httpRequest().url('https://hatter.ink/tool/tool_package_detail.jsonp') + .param('__auth_token', 'GpsVz8uxoxFW34CFhyGnTwKXQRtL3FoTA') + .param('name', name) + .param('version', version) + .get(); + var toolPackageDetailJSON = JSON.parse(toolPackageDetail.toString()); + if (toolPackageDetailJSON.status != 200) { + return null; + } + var packageName = toolPackageDetailJSON.data.name; + if (packageName.endsWith('.zip')) { packageName = packageName.substring(0, packageName.length - 4); } + else if (packageName.endsWith('.tgz')) { packageName = packageName.substring(0, packageName.length - 4); } + else if (packageName.endsWith('.tar.gz')) { packageName = packageName.substring(0, packageName.length - 7); } + if (packageName.endsWith('-bin')) { packageName = packageName.substring(0, packageName.length - 4); } + var gradleInfoJSON = { + 'package': toolPackageDetailJSON.data.url, + 'sha256': Integrity.parse(toolPackageDetailJSON.data.integrity).getDigest().asHex(), + 'path': gradleHome + '/' + packageName, + 'bin': bin + }; + gradleInfoRFile.write(JSON.stringify(gradleInfoJSON)); + return gradleInfoJSON; +}; + +var builders = { + 'ant': { + '1.7': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/ant1.7.tar.gz', + //'package': 'https://playsecurity.org/getdoc/1248_A7AA5F48FD4AD6CC21731D6DA7412028/ant1.7.tar.gz', + 'sha256': 'fb91927e662d415b6d377434a79b9ba416295d5b27c7cfdee651016e103d933f', + 'path': '~/.jssp/builder/ant-1.7/ant1.7', + 'bin': 'bin/ant' + }, + '@system': { + 'bin': 'ant' + } + }, + 'gradle': { + '1.0': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/gradle-1.0-bin.zip', + //'package': 'https://playsecurity.org/getdoc/1319_8CF093FD477F8C991C586A3FF1DDAC53/gradle-1.0-bin.zip', + 'sha256': '894bca0360a7e2040815096788f118a2dd106ff6694221b274efb9c32bce0384', + 'path': '~/.jssp/builder/gradle-1.0/gradle-1.0', + 'bin': 'bin/gradle' + }, + '3.1': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/gradle-3.1-bin.zip', + //'package': 'https://playsecurity.org/getdoc/1250_66CED6B096F6BF7C88F718F2FDFA17DD/gradle-3.1-bin.zip', + 'sha256': 'c7de3442432253525902f7e8d7eac8b5fd6ce1623f96d76916af6d0e383010fc', + 'path': '~/.jssp/builder/gradle-3.1/gradle-3.1', + 'bin': 'bin/gradle' + }, + '4.4': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/gradle-4.4-bin.zip', + //'package': 'https://playsecurity.org/getdoc/1400_ECE7856BD68513DE9BF6E8D66990443F/gradle-4.4-bin.zip', + 'sha256': 'fa4873ae2c7f5e8c02ec6948ba95848cedced6134772a0169718eadcb39e0a2f', + 'path': '~/.jssp/builder/gradle-4.4/gradle-4.4', + 'bin': 'bin/gradle' + }, + 'getPackage': (version) => { + return doGetPackage('gradle', 'bin/gradle', version); + }, + '@system': { + 'bin': 'gradle' + } + }, + 'maven': { + '2.2.1': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/apache-maven-2.2.1-bin.zip', + //'package': 'https://playsecurity.org/getdoc/1422_ABA87C5E2BD1C06F8DD898CFF67E3BDB/apache-maven-2.2.1-bin.zip', + 'sha256': 'a509c03f10ba8c7c503338c0870ae9abbb59cb06279f705d12f69b454c8cf6a1', + 'path': '~/.jssp/builder/maven-2.2.1/apache-maven-2.2.1', + 'bin': 'bin/mvn' + }, + '3.5.2': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/apache-maven-3.5.2-bin.zip', + //'package': 'https://playsecurity.org/getdoc/1421_182A3E008816352359E0690E14BD2C10/apache-maven-3.5.2-bin.zip', + 'sha256': '90e9f0d700743516d1f610fcd63a5d49751d0743db713909f9ef933747a38b8a', + 'path': '~/.jssp/builder/maven-3.5.2/apache-maven-3.5.2', + 'bin': 'bin/mvn' + }, + 'getPackage': (version) => { + return doGetPackage('maven', 'bin/mvn', version); + }, + '@system': { + 'bin': 'mvn' + } + } +}; + +var getBuildJSONInParents = (buildJSONFile) => { + var f = buildJSONFile.getAbsoluteFile(); + while (f.getParentFile() != null) { + f = f.getParentFile(); + if ($$.file(f, 'build.json').exists()) { + return $$.file(f, 'build.json'); + } + } + return null; +}; + +var main = () => { + var buildJSONFile = $$.file('build.json'); + if (!buildJSONFile.exists()) { + xprintln('[WARN] Build config file not found in current dir: build.json'); + + buildJSONFile = getBuildJSONInParents(buildJSONFile); + if (buildJSONFile == null) { + xprintln('[ERROR] Build config file not found: build.json'); + return; + } + } + var buildJSON = JSON.parse($$.rFile(buildJSONFile).string()); + var builderInfo = buildJSON.builder || buildJSON.compiler; + var javaVersion = buildJSON.java; + + if (!javaVersion) { xprintln('[ERROR] Java version is not assigned!'); return; } + if (!builderInfo) { xprintln('[ERROR] Builder info is not assigned!'); return; } + + var builder = builders[builderInfo['name']][builderInfo['version']]; + if ((builder == null) && builders[builderInfo['name']].getPackage) { + builder = builders[builderInfo['name']].getPackage(builderInfo['version']); + } + if (!builder) { xprintln('[ERROR] Builder version not found: ' + builderInfo['name'] + '-' + builderInfo['version']); return; } + var builderBin = (builderInfo['version'] == '@system') ? builder.bin : (builder.path + '/' + builder.bin); + if (builderBin.startsWith('~')) { + builderBin = $$.prop('user.home') + builderBin.substring(1); + } + + var javaHome = null; + if ($STR(javaVersion) != '@system') { // TODO ... + javaHome = javahomejs.getJavaHome(javaVersion); + if (javaHome == null) { + xprintln('[ERROR] Java version is not found: ' + javaVersion); + return; + } + } + + var commandArgs = []; + var buildCommands = []; + buildCommands.push(builderBin); + if (buildJSON.args) { + buildJSON.args.forEach((a) => { buildCommands.push(a); commandArgs.push(a); }); + } + var hasXArgsNotMatch = false; + var hasXRunsNotMatch = false; + $ARR($ARGS).forEach((a) => { + if ($STR(a).startsWith('::')) { + var aCmd = $STR(a).substring(2); + if (buildJSON.xArgs && buildJSON.xArgs[aCmd]) { + buildJSON.xArgs[aCmd].forEach((a) => { buildCommands.push(a); commandArgs.push(a); }); + return; // process next argument! + } else { + hasXArgsNotMatch = true; + xprintln('[WARN] xArgs "build.json#xArgs#' + aCmd + '" not found!'); + } + } else if ($STR(a).startsWith('...')) { + buildCommands = []; + var aCmd = $STR(a).substring(3); + if (buildJSON.xRuns && buildJSON.xRuns[aCmd]) { + buildJSON.xRuns[aCmd].forEach((a) => { buildCommands.push(a); commandArgs.push(a); }); + return; // process next argument! + } else { + hasXRunsNotMatch = true; + xprintln('[ERROR] xRuns "build.json#xRuns#' + aCmd + '" not found!'); + } + } + buildCommands.push(a); commandArgs.push(a); + }); + + if (hasXArgsNotMatch && ($ARRAY($ARGS).length == 1)) { + print('xArgs argument not found, do you want to continue(yes/no, default no)? '); + var yesNo = java.lang.System.console().readLine(); + yesNo = $STR(yesNo || 'no').toLowerCase(); + if (!(['yes', 'y'].contains(yesNo))) { + xprintln('[INFO] Exited.') + return; + } + } + if (hasXRunsNotMatch) { + return; + } + + if ((builderInfo['version'] != '@system') && (!($$.file(builderBin).exists()))) { + xprintln('[INFO] Builder not exists, downloading...'); + var nameAndVersion = builderInfo['name'] + '-' + builderInfo['version']; + var fn = builder.package.substring(builder.package.lastIndexOf('/') + 1); + if (fn.indexOf('?') > 0) { fn = fn.substring(0, fn.indexOf('?')); } + var f = $$.file('~', '.jssp', 'builder', nameAndVersion, fn); + if (!(f.exists())) { + f.getParentFile().mkdirs(); + var fos = new java.io.FileOutputStream(f); + $$.httpRequest() + .url(builder.package) + .addHeader('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36') + .get(fos, counter.getCounter2()); + fos.close(); + println(); + + var sha256 = $$.rFile(f).digest($$.digests().sha256()).asHex(); + + if ($STR(sha256) == builder.sha256) { + xprintln('[SUCCESS] Check SHA256 success.') + } else { + xprintln('[ERROR] Check SHA256 failed, actual is: ' + sha256 + ',expected: ' + builder.sha256); + f.renameTo($$.file('~', '.jssp', 'builder', nameAndVersion, fn + '.invalid.' + $$.date().millis())); + return; + } + // installBuilderScripts.push('runjs -u https://repo.examp1e.org/app/get.js ' + builder.package); + } + + var installBuilderScripts = []; + installBuilderScripts.push('cd ~/.jssp/builder/' + nameAndVersion); + if (/.*\.tar\.gz$/.test(fn) || /.*\.tgz$/.test(fn)) { + installBuilderScripts.push('tar xzvf ' + fn); + } else if (/.*\.zip$/.test(fn)) { + installBuilderScripts.push('unzip ' + fn); + } else { + xprintln('[ERROR] Extract package failed: ' + fn); + return; + } + installBuilderScripts.push(''); + + var builderIntall = $$.file('.builder_install.sh'); + $$.rFile(builderIntall).write(installBuilderScripts.join('\n')); + $$.shell().inheritIO().commands('sh', builderIntall.getName()).run(); + builderIntall.delete(); + } + + if ((builderInfo['version'] != '@system') && (!($$.file(builderBin).exists()))) { + xprintln('[ERROR] Builder bin not found!'); + return; + } + + xprintln('[INFO] JAVA_HOME = ' + (javaHome || ($$.env('JAVA_HOME') + colorprint.okgreen.render(' @system')))); + xprintln('[INFO] BUILDER = ' + builderBin + ((builderInfo['version'] == '@system') ? colorprint.okgreen.render(' @system') : '')); + xprintln('[INFO] ARGUMENTS = ' + $ARR(commandArgs).toJavaList()); + println(); + var shell = $$.shell(); + if (javaHome) { shell.env('JAVA_HOME', javaHome).env('PATH', javaHome + '/bin:' + $$.env('PATH')); } + shell.inheritIO().commands(buildCommands).run(); +}; + +main(); diff --git a/scripts/cal.js b/scripts/cal.js new file mode 100644 index 0000000..a0f4154 --- /dev/null +++ b/scripts/cal.js @@ -0,0 +1,13 @@ +#! /usr/bin/env runjs + +var main = () => { + if ($STR(__.environment.getOS().name()) == 'MacOS') { + // macOS + $$.shell().inheritIO().commands('cal', '-A', '1', '-B', '1').run(); + } else { + // Linux + $$.shell().inheritIO().commands('cal', '-3').run(); + } +}; + +main(); diff --git a/scripts/checkdependences.js b/scripts/checkdependences.js new file mode 100644 index 0000000..29f69f1 --- /dev/null +++ b/scripts/checkdependences.js @@ -0,0 +1,70 @@ +#! /usr/bin/env runjs + +var colorPrint = require('component-colorprint-ex.js'); + +var checkResultList = []; + +var getArchiveInfo = (gid, aid) => { + var archiveInfo = __.httprequest + .fromUrl('https://hatter.ink/repo/archive_info.jsonp') + .param('__auth_token', 'r7dyCJpant4VFs5vqQSphEBEEqNBXqSBiFPPG7Nz6') + .param('gid', gid) + .param('aid', aid) + .get(); + return JSON.parse($STR(archiveInfo)); +}; + +var checkNewestVersion = (printedLen, gid, aid, ver) => { + var printS = (79 - printedLen); + printS = ((printS < 0)? 0: printS) + 1; + + print(printS.repeat(' ').join('')); + var archiveInfo = getArchiveInfo(gid, aid); + if (archiveInfo.data == null) { + println('-'); + } else { + if (archiveInfo.data.latestVersion == ver) { + println(colorPrint.okgreen.render('OK')); + } else { + println(colorPrint.warning.render('NG') + ' ' + colorPrint.okgreen.render('-> ' + archiveInfo.data.latestVersion)); + checkResultList.push([gid, aid, ver].join(':') + ' -> ' + archiveInfo.data.latestVersion); + } + } +}; + +var main = () => { + var outs = $$.shell().commands('build.js', '-q', 'dependencies', '--configuration', 'compile').mergeError().start(); + var out = outs[0]; + + var lines = $STR(out).split(/\n/); + + lines.forEach((ln) => { + var indexOfSSS = ln.indexOf('--- '); + if (indexOfSSS >= 0) { + print(ln); + if (ln.indexOf('(*)') >= 0) { + println(); + } else { + var gidAidVerAndMore = ln.substring(indexOfSSS + 3).trim(); + var gid = gidAidVerAndMore.split(':')[0]; + var aid = gidAidVerAndMore.split(':')[1]; + var ver = gidAidVerAndMore.split(':')[2]; + if (gidAidVerAndMore.indexOf('->') >= 0) { + ver = gidAidVerAndMore.split('->')[1].trim(); + } + + checkNewestVersion(ln.length, gid, aid, ver); + } + } else { + println(ln); + } + }); + + if (checkResultList.length > 0) { + xprintln('[WARN] Check result:\n' + checkResultList.join('\n')); + } +}; + + +main(); + diff --git a/scripts/checkgitlabtodo.js b/scripts/checkgitlabtodo.js new file mode 100644 index 0000000..d8e75e2 --- /dev/null +++ b/scripts/checkgitlabtodo.js @@ -0,0 +1,125 @@ +#! /usr/bin/env runjs + +var argsjs = require('component-args.js'); +var timejs = require('component-time.js'); +var dingtalkrobotjs = require('component-dingtalkrobot-ex.js'); + +// curl --header "Private-Token: xxxxxxxxxxxxx" https://gitlab.com/api/v4/users/jht5945/projects | viewjson.js +// curl --header "Private-Token: xxxxxxxxxxxxx" https://gitlab.com/api/v4/projects/5327754/issues?state=opened | viewjson.js + +// https://gitlab.com/help/api/projects.md +// https://gitlab.com/help/api/issues.md + +var sampleConfig = { + "default": { + "dailyCheckHour": 9, + "checkNewItems": true, + "privateToken": "xxxxxxxxxxxxx", + "dingtalkRobotToken": "xxxxxxxxxxxxxxxxxxxxxx" + }, + "list": [{ + "projectId": 5327754, + "dailyCheckHour": 9, + "checkNewItems": true, + "privateToken": "xxxxxxxxxxxxx", + "dingtalkRobotToken": "xxxxxxxxxxxxxxxxxxxxxx", + "messageFootNote": "https://gitlab.com/xxxxxxx/xxxxxxxxxxxxx/issues" + }] +}; + +var issueToString = (issue) => { + var createdAt = $$.date().fmt('yyyy-MM-dd\'T\'HH:mm:ss.SSSXXX').parse(issue.created_at); + var it = [' - ', issue.title]; + it.push(' (' + timejs.formatDuration(createdAt.getTime()) + ')'); + if (issue.labels && issue.labels.length > 0) { + it.push(' [' + issue.labels.join(', ') + ']'); + } + if (issue.due_date) { + it.push(', due: ' + timejs.formatDueInDays($$.date().fmt('yyyy-MM-dd').parse(issue.due_date))); + } + if (issue.weight != null) { + it.push(', weight: ' + issue.weight); + } + return it.join(''); +}; + +var main = () => { + var args = argsjs.parseDefARGs(); + var config = $$.file(args[0] || '~/.gitlab_todo_config.json'); + if (!(config.exists())) { + xprintln('[ERROR] config file not exists: ' + args[0]); + return; + } + var configJSON = JSON.parse($$.rFile(config).string() || '{}'); + var defaultConfig = configJSON['default']; + var configList = configJSON['list'] || []; + + configList.forEach((config) => { + var startMillis = $$.date().millis(); + xprintln('[INFO] Check project, id: ' + config.projectId); + var localConfigPath = $$.file('~/.jssp/gitlab_todo/localconfig'); + if (!(localConfigPath.exists())) { localConfigPath.mkdirs(); } + var projectLocalConfig = $$.file(localConfigPath, 'config_' + config.projectId + '.json'); + var projectLocalConfigJSON = {}; + if (projectLocalConfig.exists()) { projectLocalConfigJSON = JSON.parse($$.rFile(projectLocalConfig).string()); } + + var doDailyCheckHour = false; + var todayYMD = $STR($$.date().fmt('yyyy-MM-dd').format($$.date().today())); + var hour = $$.asInt($$.date().fmt('H').format($$.date().today())); + if (todayYMD != projectLocalConfigJSON.checkedYMD) { + if (hour == ((config.dailyCheckHour != null) ? config.dailyCheckHour : defaultConfig.dailyCheckHour)) { + doDailyCheckHour = true; + } + } + var hasNewItems = false; + var doCheckNewItems = (config.checkNewItems != null) ? config.checkNewItems : defaultConfig.checkNewItems; + xprintln('[INFO] Project config: doDailyCheckHour=' + doDailyCheckHour + ', doCheckNewItems=' + doCheckNewItems); + + if (doDailyCheckHour || doCheckNewItems) { // DO CHECK + var url = 'https://gitlab.com/api/v4/projects/' + config.projectId + '/issues?state=opened'; + xprintln('[INFO] Get url: ' + url); + var openedIssues = $$.httpRequest().url(url) + .header('Private-Token', config.privateToken || defaultConfig.privateToken) + .get(); + + var openedIssuesJSON = JSON.parse(openedIssues); + if (openedIssuesJSON && (openedIssuesJSON.length > 0)) { + if (doDailyCheckHour) { + var msg = []; + msg.push((config.title || '') + ' (' + openedIssuesJSON.length + ' items):'); + openedIssuesJSON.forEach((issue) => { + msg.push(issueToString(it)); + }); + if (config.messageFootNote) { + msg.push(''); + msg.push(config.messageFootNote); + } + dingtalkrobotjs.sendText(config.dingtalkRobotToken || defaultConfig.dingtalkRobotToken, msg.join('\n')); + projectLocalConfigJSON.checkedYMD = todayYMD; + } + if (doCheckNewItems) { + projectLocalConfigJSON.checkedIssueIds = projectLocalConfigJSON.checkedIssueIds || []; + var newIssuesJSON = openedIssuesJSON.filter((issue) => { + return (projectLocalConfigJSON.checkedIssueIds.indexOf(issue.id) < 0); + }); + if (newIssuesJSON && (newIssuesJSON.length > 0)) { + var msg = []; + msg.push('New items found (' + newIssuesJSON.length + ' items):'); + newIssuesJSON.forEach((issue) => { + msg.push(issueToString(issue)); + projectLocalConfigJSON.checkedIssueIds.push(issue.id); + }); + hasNewItems = true; + dingtalkrobotjs.sendText(config.dingtalkRobotToken || defaultConfig.dingtalkRobotToken, msg.join('\n')); + } + } + } + if (doDailyCheckHour || (doCheckNewItems && hasNewItems)) { + $$.rFile(projectLocalConfig).write(JSON.stringify(projectLocalConfigJSON)); + } + } + xprintln('[INFO] Finish check project, cost: ' + ($.date().millis() - startMillis) + 'ms'); + }); +}; + +main(); diff --git a/scripts/checkgitupdate.js b/scripts/checkgitupdate.js new file mode 100644 index 0000000..ec9f08e --- /dev/null +++ b/scripts/checkgitupdate.js @@ -0,0 +1,14 @@ +#!/usr/bin/env runjs + +var System = java.lang.System; + +var main = () => { + var r = $STR($$.shell().commands('git', 'fetch', '--dry-run').mergeError().start()[0]); + if (r.trim().length > 0) { + System.exit(1); + } + System.exit(0); +}; + +main(); + diff --git a/scripts/checkscripts.js b/scripts/checkscripts.js new file mode 100644 index 0000000..3389e83 --- /dev/null +++ b/scripts/checkscripts.js @@ -0,0 +1,33 @@ +#!/usr/bin/env runjs + +var argsjs = require('component-args.js'); +var colorprint = require('component-colorprint-ex.js'); + +var main = function() { + var args = argsjs.parseDefARGs([]); + + $ARR(__.rfile.from('.').file().listFiles()).forEach((f) => { + var fn = f.getName(); + var fnLn = fn.length; + print('Checking: ' + fn + __.stringutil.repeat(' ', (44 - fnLn))); + if (!(f.isFile())) { + print('[SKIP]'); + } else { + var fBs = __.httprequest.fromUrl('https://hatter.ink/script/get.json?nocontent=true&name=' + fn).get(); + var fJson = JSON.parse(fBs.string()); + if (fJson.status == 404) { + print(colorprint.bold.print('[NOT FOUND]')); + } else { + var sha1 = $STR(__.rfile.from(f).digest($$.digests().sha1()).asHex()); + if (sha1 == fJson.data.sha1) { + print(colorprint.okgreen.print('[OK]')); + } else { + print(colorprint.warning.print('[NG]')); + } + } + } + println(); + }); +} + +main(); diff --git a/scripts/cmd.js b/scripts/cmd.js new file mode 100644 index 0000000..0ccb669 --- /dev/null +++ b/scripts/cmd.js @@ -0,0 +1,22 @@ +#!/usr/bin/env runjs + +var DefaultRollCounter = Packages.me.hatter.tools.commons.io.DefaultRollCounter; + +var cmdRFile = __.rfile.from('~/.jssp/cache/cmd.jar'); +var cmdUrl = 'https://a.hatter.ink/cmd.jar'; + +if (cmdRFile.notExists()) { + var bs = $$.httpRequest().url(cmdUrl).get(new DefaultRollCounter().prefix('Downloading ... ')); + cmdRFile.write(bs); +} + +requireJAR('file://' + cmdRFile.file()); + +var JarLauncher = Packages.org.springframework.boot.loader.JarLauncher; + +var main = () => { + JarLauncher.main($ARGS); +}; + +main(); + diff --git a/scripts/convertcsv2xls.js b/scripts/convertcsv2xls.js new file mode 100644 index 0000000..15b8607 --- /dev/null +++ b/scripts/convertcsv2xls.js @@ -0,0 +1,53 @@ +#! /usr/bin/env runjs + +requireJAR('commons-csv-1.4.jar'); +requireJAR('poi-3.15.jar'); + +var FileOutputStream = java.io.FileOutputStream; +var StringUtil = Packages.me.hatter.tools.commons.string.StringUtil; +var CSVParser = Packages.org.apache.commons.csv.CSVParser; +var CSVFormat = Packages.org.apache.commons.csv.CSVFormat; +var HSSFWorkbook = Packages.org.apache.poi.hssf.usermodel.HSSFWorkbook; +var HSSFSheet = Packages.org.apache.poi.hssf.usermodel.HSSFSheet; +var HSSFRow = Packages.org.apache.poi.hssf.usermodel.HSSFRow; +var HSSFCell = Packages.org.apache.poi.hssf.usermodel.HSSFCell; +var Cell = Packages.org.apache.poi.ss.usermodel.Cell; + +var main = () => { + if ($ARGS == null || $ARGS.length == 0) { + println('convertcsv2xls.js - Convert CSV to Excel.') + println(); + println('ERROR: NO arguments assigned!'); + println('convertcsv2xls.js filename.csv [filename.xls]'); + return; + } + var csvFile = $$.file($ARGS[0]); + if (!csvFile.exists()) { + println('[ERROR] File not exists: ' + $ARGS[0]); + return; + } + + var xlsFile = ($ARGS.length > 1)? $ARGS[1]: (StringUtil.substringBeforeLast(csvFile.getName(), '.') || csvFile.getName()) + '.xls'; + + var book = new HSSFWorkbook(); + var sheet = book.createSheet('new sheet'); + + println('Read CSV file: ' + csvFile); + var parser = CSVParser.parse(csvFile, $$.charset('UTF-8'), CSVFormat.EXCEL); + $EACH(parser, (record, index) => { + println('Write excel row: ' + index); + var row = sheet.createRow(index); + $EACH(record, (item, cellIndex) => { + var cell = row.createCell(cellIndex); + cell.setCellType(Cell.CELL_TYPE_STRING); + cell.setCellValue($$.str(item)); + }); + }); + + println('Write excel file: ' + xlsFile); + var fout = new FileOutputStream(xlsFile); + book.write(fout); + fout.close(); +}; + +main(); diff --git a/scripts/createproject.js b/scripts/createproject.js new file mode 100644 index 0000000..e5ea61f --- /dev/null +++ b/scripts/createproject.js @@ -0,0 +1,70 @@ +#!/usr/bin/env runjs + +var argsjs = require('component-args.js'); + +printUsage = () => { + println('createproject.js springboot|jar'); +}; + +createDirs = () => { + __.rfile.from('src/main/java').file().mkdirs(); + __.rfile.from('src/main/resources').file().mkdirs(); + __.rfile.from('src/test/java').file().mkdirs(); + __.rfile.from('src/test/resources').file().mkdirs(); +}; + +createFileGitignore = () => { + var gitignores = [ + 'build', + 'classes', + '.DS_Store', + '.gradle', + '.classpath', + '.project', + '.settings', + '*.iml', + '*.ipr', + '*.iws' + ]; + __.rfile.from('.gitignore').write(gitignores.join('\n')); +}; + +createProject = (gradleFn) => { + var buildJsonRFile = __.rfile.from('build.json'); + var buildGradleRFile = __.rfile.from('build.gradle'); + + if (buildJsonRFile.exists() || buildGradleRFile.exists()) { + xprintln('[ERROR] File build.json or build.gradle exists.'); + return; + } + + xprintln('[INFO] Get build.json'); + var buildJsonBs = __.httprequest.fromUrl('https://hatter.ink/script/get.action?name=build.json').get(); + xprintln('[INFO] Get build.gradle') + var buildGradleBs = __.httprequest.fromUrl('https://hatter.ink/script/get.action?name=' + gradleFn).get(); + + buildJsonRFile.write(buildJsonBs); + buildGradleRFile.write(buildGradleBs); + + createDirs(); + createFileGitignore(); +}; + +main = () => { + var args = argsjs.parseDefARGs([]); + if ((args == null) || (args.length == 0)) { + printUsage(); + return; + } + if (args[0] == 'springboot') { + createProject('build_springboot_template.gradle'); + } else if (args[0] == 'jar') { + createProject('build_jar_template.gradle'); + } else { + xprintln('[WARN] Unknown commant: ' + args[0]); + } +}; + +main(); + +// @SCRIPT-SIGNATURE-V1: yk-r1.ES256.20250105T215717+08:00.MEUCIQCiea2KACCkhb1/qMvnYGRKWOAzDABzM4LHYoVVousLSAIgIKvu8xkItW3FSmYMJHye9jdcIPBbRto9yGUrnIyZyIs= diff --git a/scripts/createrunjs.js b/scripts/createrunjs.js new file mode 100644 index 0000000..24ce5e2 --- /dev/null +++ b/scripts/createrunjs.js @@ -0,0 +1,86 @@ +#!/usr/bin/env runjs + +var consolejs = require('component-console.js'); +var filesystemjs = require('component-filesystem.js'); + +var RUNJS_HEAD_LINE = '#!/usr/bin/env runjs'; +var RUNJS_COMPONENT_CONFIG_URL = 'https://hatter.ink/script/get_scripts.json?type=runjs-component'; + +var main = () => { + var runjsFn = $$.file(consolejs.readLineEx('Input your runjs filename: ')); + if (runjsFn.exists()) { + xprintln('[ERROR] File exists: ' + runjsFn); + return; + } + var componentsJSON = JSON.parse($$.httpRequest().skipCertCheck().url(RUNJS_COMPONENT_CONFIG_URL).get().string()); + var components = []; + componentsJSON.scripts.forEach((c, i) => { + if (!(['component-colorprint.js', 'component-diffutil.js', 'component-dingtalkrobot.js', + 'component-filechooser.js', 'component-gpg.js', 'component-helloworld.js', + 'component-helloworld2.js', 'component-httpserver.js', 'component-json.js', + 'component-shannonentropy.js', 'component-sqlitedataaccess.js', 'component-swing.js'].contains(c))) { + components.push(c); // old js components + } + }); + + xprintln('[INFO] Components: '); + components.forEach((c, i) => { + var ln = repeat(' ', (3 - $STR(i).length)) + i + ': ' + c; + print(ln + repeat(' ', 60 - ln.length)); + if (((i + 1) % 2) == 0) { println(); } + }); + if (components.length % 2 != 0) { println(); } + + var selectedComponents = consolejs.readLine('Select components(split with \',\'): '); + + var componentIds = []; + $ARR(selectedComponents.split(',')).forEach((cid) => { + cid = cid.trim(); + if (cid == '') { return; } + componentIds.push(parseInt(cid)); + }); + + var isComponent = runjsFn.getName().startsWith('component-'); + var selectedComponentNames = []; + var buf = []; + if (!isComponent) { buf.push(RUNJS_HEAD_LINE); } + buf.push(''); + componentIds.forEach((cid) => { + var c = components[cid]; + if (c == null) { + xprintln('[WARN] Component not found: ' + cid); + } else { + selectedComponentNames.push(c); + var n = c.substring('component-'.length).replace('-ex', '').replace('.js', '') + 'js'; + buf.push('var ' + n + ' = require(\'' + c + '\');'); + } + }); + buf.push(''); + if (isComponent) { + buf.push('var sample = () => {'); + buf.push(' // TODO'); + buf.push('}'); + buf.push(''); + buf.push('if (typeof exports == \'object\') {'); + buf.push(' exports.sample = sample;'); + buf.push('}'); + buf.push(''); + } else { + buf.push('var main = () => {'); + if (selectedComponentNames.contains('component-args.js')) { + buf.push(' var args = argsjs.parseDefARGs([]);'); + } + buf.push(' xprintln(\'[OK] Hello World!\'); // TODO'); + buf.push('}'); + buf.push(''); + buf.push('main();'); + buf.push(''); + } + $$.rFile(runjsFn).write(buf.join('\n')); + if (!isComponent) { filesystemjs.chmodAddExec(runjsFn); } + + xprintln('[SUCCESS] Create file success: ' + runjsFn); +}; + +main(); + diff --git a/scripts/date.js b/scripts/date.js new file mode 100644 index 0000000..cfe6f51 --- /dev/null +++ b/scripts/date.js @@ -0,0 +1,12 @@ +#! /usr/bin/env runjs + +var TimeZone = java.util.TimeZone; +var SimpleDateFormat = java.text.SimpleDateFormat; + +var main = () => { + var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); + sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + println(sdf.format(new java.util.Date())); +}; + +main(); diff --git a/scripts/decrypt.js b/scripts/decrypt.js new file mode 100644 index 0000000..733ab2f --- /dev/null +++ b/scripts/decrypt.js @@ -0,0 +1,36 @@ +#! /usr/bin/env runjs + +requireJAR('bcprov-ext-jdk15on-154.jar'); +requireJAR('crypto-1.0.jar'); + +var FileOutputStream = Packages.java.io.FileOutputStream; +var DecryptTool = Packages.me.hatter.tools.crypto.stream.DecryptTool; + + +var main = () => { + if ($ARGS.length != 3) { + xprintln('[ERROR] parameter error, decrypt.js AES_KEY FILE_NAME_ENC FILE_NAME'); + return; + } + var k = __.bytes.fromHex($ARGS[0]).bytes(); + var encF = $$.rFile($ARGS[1]); + var dstF = $$.rFile($ARGS[2]); + if (encF.notExists()) { + xprintln('[ERROR] Enc file not exists.'); + return; + } + if (dstF.exists()) { + xprintln('[ERROR] Dest file exists.'); + return; + } + var is = encF.inputStream(); + var dt = new DecryptTool(is, k); + var os = dstF.outputStream(); + xprintln('[INFO] Descrypt ' + encF.file() + ' -> ' + dstF.file() + ' ...'); + dt.decrypt(os); + os.close(); + is.close(); + xprintln('[OK] Decrypt file finished.'); +}; + +main(); diff --git a/scripts/digcaa.js b/scripts/digcaa.js new file mode 100644 index 0000000..781346b --- /dev/null +++ b/scripts/digcaa.js @@ -0,0 +1,36 @@ +#! /usr/bin/env runjs + +var StringUtil = Packages.me.hatter.tools.commons.string.StringUtil; +var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes; +var RReader = Packages.me.hatter.tools.commons.io.RReader; + +var main = () => { + if ($ARGS == null || $ARGS.length == 0) { + println('digcaa.js - Dig CAA.') + println(); + println('ERROR: NO arguments assigned!'); + println('digcaa.js '); + return; + } + var result = $$.shell().commands('dig', '+short', '-t', 'TYPE257', $ARGS[0]).start(); + var out = result[0].string(); + var err = result[1].string(); + if ((err != null) && (err != '')) { + println('+ ERROR: ' + err) + } + $ARRAY(RReader.from(out).listAndClose()) + .filter((ln) => {return (ln.trim() != '');}) + .forEach((ln) => { + var ss = $$.asList(ln.split(/\s+/)); + var f = ss[2].substring(0, 2); + var l = ss[2].substring(2, 4); + var p1 = ss[2].substring(4, (4 + parseInt(l, 16) * 2)); + var p2 = ss[2].substring(4 + p1.length); + if (ss.size() > 3) { + for (var i = 3; i < ss.size(); i++) { p2 += ss[i]; } + } + println(ln + StringUtil.repeat(' ', 50 - ln.length) + ' --> ' + parseInt(f, 16) + ' ' + Bytes.fromHex(p1) + ' "' + Bytes.fromHex(p2) + '"'); + }); +}; + +main(); diff --git a/scripts/digestjs.js b/scripts/digestjs.js new file mode 100644 index 0000000..33a1fa7 --- /dev/null +++ b/scripts/digestjs.js @@ -0,0 +1,41 @@ +#! /usr/bin/env runjs + +var hashjs = require('component-hashjs.js'); + +var main = () => { + var args = $ARRAY($ARGS); + if (args.length < 1) { + println('No args...'); + println(); + println('digestjs.js ') + return; + } + args.forEach((f) => { + var fi = $$.file(f); + if (fi.isDirectory()) { xprintln('[WARN] Skip directory: ' + fi); return; } + if (!(fi.getName().endsWith('.js'))) { xprintln('[WARN] Skip non js: ' + fi); return; } + + var bytes = $$.rFile(fi).Bytes(); + var list = bytes.list(); + var digestJSON = hashjs.__getDigestJSON(list); + + var jsSHA256Hex = hashjs.__calcSHA256Hex(list); + if (digestJSON == null) { + xprintln('[OK] Write file: ' + fi + ', SHA256: ' + jsSHA256Hex); + digestJSON = { 'SHA256': jsSHA256Hex }; + list.add(hashjs.COMMENT_HASH_TAG + JSON.stringify(digestJSON)); + $$.rFile(fi).write($ARR(list).join('\n')); + } else { + if (digestJSON.SHA256 == jsSHA256Hex) { + xprintln('[INFO] SHA256 matches, Skip file SHA256 update: ' + fi); + } else { + xprintln('[OK] Update file: ' + fi + ', SHA256: ' + digestJSON.SHA256 + ' >> ' + jsSHA256Hex); + digestJSON = { 'SHA256': jsSHA256Hex }; + list.add(hashjs.COMMENT_HASH_TAG + JSON.stringify(digestJSON)); + $$.rFile(fi).write($ARR(list).join('\n')); + } + } + }); +}; + +main(); diff --git a/scripts/doubanbook.js b/scripts/doubanbook.js new file mode 100644 index 0000000..c398743 --- /dev/null +++ b/scripts/doubanbook.js @@ -0,0 +1,104 @@ +#! /usr/bin/env runjs + +var oss = require('component-oss.js'); +var fastJSON = require('component-json-ex.js'); + +oss.requireJARs(); +requireJAR('jsoup-1.8.1.jar'); + +var Jsoup = Packages.org.jsoup.Jsoup; +var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil; +var KeyValue = Packages.me.hatter.tools.commons.network.HttpRequest.KeyValue; + +var main = () => { + if ($ARGS.length < 1) { + println('No args!!!'); + return; + } + + var config = $$.rFile('~', '.jssp/config/osssendfile.json').string(); + var configJSON = JSON.parse(config); + + var url = $ARGS[0]; + var content = $$.httpRequest().url(url).get().toString(); + + var doc = Jsoup.parse(content); + var title = doc.select("#wrapper h1 span").get(0).text(); + var bigImg = doc.select(".subject #mainpic a").get(0).attr("href"); + var smallImg = doc.select(".subject #mainpic a img").get(0).attr("src"); + var bookInfo = doc.select(".subject #info").get(0).text().replaceAll("\\b([^ ]*:)", "\n$1").trim(); + + var bookAttrs = $$.linkedMap(); + $ARR(IOUtil.readToList(bookInfo)).forEach((l) => { + l = l.trim(); + var indexOfComma = l.indexOf(':'); + var k = l.substring(0, indexOfComma).trim(); + var v = l.substring(indexOfComma + 1).trim(); + + bookAttrs.put(k, v); + }); + + println('[INFO] Book details:'); + println('Name : ' + title); + println('Big img : ' + bigImg); + println('Small img : ' + smallImg); + println('Detail info : ' + fastJSON.prettyJavaJSON(bookAttrs)); + + print('Confirm [Y/N]:'); + var confirm = java.lang.System.console().readLine(); + if (!(confirm && $STR(confirm.trim()).toLowerCase() == 'y')) { + xprintln('[ERROR] Y or y is not selected, end!'); + return; + } + + var uploadImg = (imgUrl) => { + println('[INFO] Send image: ' + imgUrl); + + var params = $$.list(); + params.add(new KeyValue('jsonp', '1')); + params.add(new KeyValue('token', configJSON.token)); + params.add(new KeyValue('url', imgUrl)); + params.add(new KeyValue('title', title + imgUrl.substring(imgUrl.lastIndexOf('.')))); + params.add(new KeyValue('keywords', 'Book,Image,Book Cover')); + params.add(new KeyValue('description', 'Book: ' + title + ', url: ' + url + ', detail: ' + fastJSON.prettyJavaJSON(bookAttrs))); + var res = $$.httpRequest().url('https://playsecurity.org/doc/addDoc.jsonp').post(params); + + var resJSON = JSON.parse(res); + if (resJSON.status == 200) { + xprintln('[SUCCESS] Send image to doc list successed: ' + res); + } else { + xprintln('[FAIL] Send image to doc list failed: ' + res); + throw ('[FAIL] Send image to doc list failed: ' + res); + } + return 'https://playsecurity.org/getdoc/' + resJSON['id'] + '_' + resJSON['etag'] + '/' + imgUrl.substring(imgUrl.lastIndexOf('/') + 1); + }; + var newSmallImg = uploadImg(smallImg); + var newBigImg = newSmallImg; + if ($STR(smallImg) != $STR(bigImg)) { + newBigImg = uploadImg(bigImg); + } + + { + println('[INFO] Send book info') + var params = $$.list(); + params.add(new KeyValue('jsonp', '1')); + params.add(new KeyValue('token', configJSON.token)); + params.add(new KeyValue('url', url)); + params.add(new KeyValue('title', title)); + params.add(new KeyValue('type', '')); + params.add(new KeyValue('bigImg', newBigImg)); + params.add(new KeyValue('smallImg', newSmallImg)); + params.add(new KeyValue('bookInfo', $$.stringify(bookAttrs))); + var res = $$.httpRequest().url('https://playsecurity.org/book/addBook.jsonp').post(params); + + var resJSON = JSON.parse(res); + if (resJSON.status == 200) { + xprintln('[SUCCESS] Send book to book list successed: ' + res); + } else { + xprintln('[FAIL] Send book to book list failed: ' + res); + throw ('[FAIL] Send book to book list failed: ' + res); + } + } +}; + +main(); diff --git a/scripts/enc.js b/scripts/enc.js new file mode 100644 index 0000000..b471c74 --- /dev/null +++ b/scripts/enc.js @@ -0,0 +1,173 @@ +#! /usr/bin/env runjs + +var argsjs = require('component-args.js'); +var RFile = Packages.me.hatter.tools.commons.io.RFile; + +var main = () => { + var parsedArgs = argsjs.parseDefARGs([]); + + var actions = ['desc', 'show', 'cat', 'edit', 'create']; + var matchAction = (parsedArgs.length == 0)? []: actions.filter((a) => { return a.startsWith(parsedArgs[0]) }); + if (matchAction == 0) { + println('No or error args, usage:'); + println(' enc [-k KEY_ID] desc|show|cat|edit|create'); + return; + } + + if (matchAction.length > 1) { + println('Match more than one action: ' + JSON.stringify(matchAction)); + return; + } + parsedArgs[0] = matchAction[0]; + + if (parsedArgs[0] == 'desc') { + if (parsedArgs.length == 1) { + println('File name is not assigned.'); + return; + } + $$.shell().commands('pgpdump', parsedArgs[1]).inheritIO().run(); + return; + } + + var userDir = $$.prop('user.dir'); + var pgpKeyId = parsedArgs.val('k'); + + if (pgpKeyId == null) { + var encJSConf = $$.file($$.prop('user.home'), '.enc.js.conf'); + if (!encJSConf.exists()) { + println('Config file ~/.enc.js.conf not found.'); + return; + } + var pgpKeyId = RFile.from(encJSConf).string().trim(); + if (pgpKeyId.length == 0) { + println('PGP key id is empty.'); + return; + } + } + + if (parsedArgs[0] == 'create') { + var fname; + if (parsedArgs.length > 1) { + fname = parsedArgs[1]; + } else { + print('Please input filename: '); + fname = java.lang.System.console().readLine(); + } + if (fname.length == 0) { + println('File name is not inputed.'); + return; + } + var fn = fname.replace(/[^a-zA-Z0-9_.]/g, '_'); + if ($$.file(userDir, fn).exists()) { + println('File exists: ' + fn); + return; + } + if ($$.file(userDir, fn + '.asc').exists()) { + println('File exists: ' + fn + '.asc'); + return; + } + + requireJS('component-swing.js'); + + var txt = showWindow('Create - ' + fn, '', 'Input message:', true).get(); + if (txt == null) { + println('Message is not inputed.'); + return; + } + + RFile.from($$.file(userDir, fn)).write(txt); + $$.shell().commands('sh', '-c', 'gpg -r ' + pgpKeyId + ' -e -a --no-comment --comment "https://hatter.in/key" ' + fn).start(); + if ($$.file(userDir, fn + '.asc').exists()) { + $$.file(userDir, fn).delete(); + println('CREATE SUCCESS.'); + } + + return; + } + + var userDirFile = $$.file(userDir); + var encFiles = $ARRAY(userDirFile.list()).filter((f) => { return (f.endsWith('.gpg') || f.endsWith('.asc')); }); + if (encFiles.length == 0) { + println('Can NOT find any .gpg or .asc file.'); + return; + } + var argFilterEncFiles = parsedArgs.length > 1? encFiles.filter((f) => { return f == parsedArgs[1]; }): []; + var selectFile = (argFilterEncFiles.length > 0)? argFilterEncFiles[0]: null; + if (selectFile == null && encFiles.length > 1) { + println('Please select one file:'); + encFiles.forEach((f, i) => { + println(' ' + i + ': ' + f); + }); + print('Input a number 0-' + (encFiles.length - 1) + ': '); + var ln = java.lang.System.console().readLine(); + var idx = 0; + try { + idx = java.lang.Integer.parseInt(ln); + if ((idx < 0) || (idx >= encFiles.length)) { + println("Index range error: " + idx); + return; + } + + selectFile = encFiles[idx]; + } catch (e) { + println('Parse error: ' + (e.getMessage == null)? e: e.getMessage()); + return; + } + } + if ((selectFile == null) && (encFiles.length == 1)) { + selectFile = encFiles[0]; + } + if (selectFile == null) { + println('File is not selected.'); + return; + } + + var result = $$.shell().commands('sh', '-c', 'cat ' + selectFile + ' | gpg').start(); + var out = result[0].string(); + var err = result[1].string(); + if (err.contains('public key decryption failed')) { + println('+ Decrypt file FAILED: ' + selectFile); + if (!Packages.me.hatter.tools.jssp.main.StandaloneMain.JSSP_MAIN_MUTE) { + println("ERROR detail:\n" + err); + } + return; + } + + if (parsedArgs[0] == 'cat') { + println('Enc message: ' + selectFile); + println(repeat('-', 80)); + println(out); + println(repeat('-', 80)); + return; + } + + var listOnlyKeyIdOut = $$.shell().commands('gpg', '--list-only', '--list-packets', selectFile).start()[1]; + var keyIds = $STR(listOnlyKeyIdOut).split('\n') + .filter((x) => { return x.contains('ID '); }) + .map((x) => { return x.replace(/.*ID\s+([0-9a-fA-F]+)[,\s]+.*/, '$1'); }); + println('Encrypted key ids: [' + keyIds.join(', ') + ']'); + + requireJS('component-swing.js'); + + var actFLUC = parsedArgs[0].substring(0, 1).toUpperCase() + parsedArgs[0].substring(1); + var txt = showWindow(actFLUC + ' - ' + selectFile, out, actFLUC + ' encrypted message:', parsedArgs[0] == 'edit').get(); + + if (txt != null) { + // backup + $$.file(userDir, selectFile).renameTo($$.file(userDir, selectFile + '.back')); + // write text + var txtFile = selectFile.substring(0, selectFile.length - 4) + RFile.from($$.file(userDir, txtFile)).write(txt); + + $$.shell().commands('sh', '-c', 'gpg ' + keyIds.map((x) => {return '-r ' + x; }).join(' ') + ' -e -a --no-comment --comment "https://hatter.in/key" ' + txtFile).start(); + if ($$.file(userDir, txtFile + '.asc').exists()) { + $$.file(userDir, txtFile).delete(); + println('UPDATE SUCCESS.'); + } + } else { + println('BYE.'); + } +}; + +main(); +java.lang.System.exit(0); diff --git a/scripts/ffmpegfaststart.js b/scripts/ffmpegfaststart.js new file mode 100644 index 0000000..c368b73 --- /dev/null +++ b/scripts/ffmpegfaststart.js @@ -0,0 +1,29 @@ +#!/usr/bin/env runjs + + +var main = function() { + if ($ARGS.length == 0) { + xprintln('[ERROR] No arguments.'); + return; + } + var f = __.rfile.from($ARGS[0]); + if (f.notExists()) { + xprintln('[ERROR] File not exists: ' + $ARGS[0]); + return; + } + + var o = $ARGS[0]; + var n = $ARGS[0] + '.processed.mp4'; + xprintln('[INFO] Start process: ' + o); + $$.shell(true).commands('ffmpeg', '-i', o, '-c:a', 'copy', '-c:v', 'copy', '-movflags', 'faststart', n).run(); + + $$.sleep(500); + if ($ARGS.length > 1 && $STR($ARGS[1]) == "re") { + if (__.rfile.from(n).exists()) { + __.rfile.from(o).file().delete(); + $$.shell(true).commands("mv", n, o).run(); + } + } +} + +main(); diff --git a/scripts/ffmpegscale.js b/scripts/ffmpegscale.js new file mode 100644 index 0000000..ca92cc4 --- /dev/null +++ b/scripts/ffmpegscale.js @@ -0,0 +1,30 @@ +#!/usr/bin/env runjs + + +var main = function() { + if ($ARGS.length == 0) { + xprintln('[ERROR] No arguments.'); + return; + } + var f = __.rfile.from($ARGS[0]); + if (f.notExists()) { + xprintln('[ERROR] File not exists: ' + $ARGS[0]); + return; + } + var scale = "480"; // 320 + + var o = $ARGS[0]; + var n = $ARGS[0] + '.' + scale + 'ff.mp4'; + xprintln('[INFO] Start process: ' + o); + $$.shell(true).commands('ffmpeg', '-i', o, '-c:a', 'copy', '-movflags', 'faststart', '-filter:v', 'scale='+scale+':-1', n).run(); + + $$.sleep(500); + if ($ARGS.length > 1 && $STR($ARGS[1]) == "re") { + if (__.rfile.from(n).exists()) { + __.rfile.from(o).file().delete(); + $$.shell(true).commands("mv", n, o).run(); + } + } +} + +main(); diff --git a/scripts/finding.js b/scripts/finding.js new file mode 100644 index 0000000..5770bea --- /dev/null +++ b/scripts/finding.js @@ -0,0 +1,14 @@ +#! /usr/bin/env runjs + +requireJAR('findingall.jar'); + +var main = () => { + var args = $$.list(); + args.add('-o'); + args.add('UTF-8'); + args.add('---NCL'); + $ARR($ARGS).forEach((a) => { args.add(a); }); + Packages.me.hatter.tools.finding.Finding.main(args.toArray($$.array(java.lang.String.class, 0))); +}; + +main(); diff --git a/scripts/generate_ecp256_keypair.js b/scripts/generate_ecp256_keypair.js new file mode 100644 index 0000000..997441a --- /dev/null +++ b/scripts/generate_ecp256_keypair.js @@ -0,0 +1,19 @@ +#! /usr/bin/env runjs + +requireJAR('maven:me.hatter:crypto:1.9'); + +var KeyPairTool = Packages.me.hatter.tools.commons.security.key.KeyPairTool; +var PKType = Packages.me.hatter.tools.commons.security.key.PKType; +var PEMUtil = Packages.me.hatter.tools.commons.security.pem.PEMUtil; + + +var main = () => { + var kp = KeyPairTool.ins(PKType.secp256r1).generateKeyPair().getKeyPair(); + var privatePem = PEMUtil.printPEM("PRIVATE KEY", kp.getPrivate().getEncoded()); + var publicPem = PEMUtil.printPEM("PUBLIC KEY", kp.getPublic().getEncoded()); + println("[OK] Private key PEM:\n" + privatePem); + println("[OK] Public key PEM:\n" + publicPem); +}; + +main(); + diff --git a/scripts/generatecreatesql.js b/scripts/generatecreatesql.js new file mode 100644 index 0000000..e1339fb --- /dev/null +++ b/scripts/generatecreatesql.js @@ -0,0 +1,40 @@ +#! /usr/bin/env runjs + +requireJAR('dataaccess-1.0.jar'); + +var System = java.lang.System; +var DataAccessUtil = Packages.me.hatter.tools.dataaccess.util.DataAccessUtil; +var SQLiteDialectImpl = Packages.me.hatter.tools.dataaccess.dialect.impl.SQLiteDialectImpl; +var InMemoryCompiler = Packages.me.hatter.tools.commons.classloader.compile.InMemoryCompiler; +var EntityJavaSourceCodeGenerateTool = Packages.me.hatter.tools.dataaccess.entity.EntityJavaSourceCodeGenerateTool; + +var main = () => { + var accessJarPath = System.getProperty('user.home') + '/.jssp/cache/dataaccess-1.0.jar'; + var classPath = System.getProperty('java.class.path') + ':' + accessJarPath; + var files = $$.file('.').listFiles(); + var allCreateSQLs = []; + $ARRAY(files).filter((f) => { return f.isFile() && f.getName().endsWith('.entity.json') }).forEach((f) => { + println('Entity JSON file: ' + f); + var json = $$.rFile(f).string(); + var sourceCode = EntityJavaSourceCodeGenerateTool.instance().config(json).generate(); + $$.rFile(f.getName() + '.source.txt').write(sourceCode.getCharContent(true)); + + var clazz = InMemoryCompiler.systemInstance().classPath(classPath).compile(sourceCode); + var createSQL = DataAccessUtil.generateCreateSQL(clazz, new SQLiteDialectImpl()); + + println('... ' + clazz); + allCreateSQLs.push(createSQL + ';'); + }); + + println(); + if (allCreateSQLs.length == 0) { + println('No Create SQL Generated.'); + } else { + println('All Create SQL:'); + allCreateSQLs.forEach((sql) => { + println(' ' + sql); + }); + } +}; + +main(); diff --git a/scripts/get.js b/scripts/get.js new file mode 100644 index 0000000..c7ecf5c --- /dev/null +++ b/scripts/get.js @@ -0,0 +1,111 @@ +#! /usr/bin/env runjs + +var argsEx = require('component-args.js'); +var bytes = require('component-bytes.js'); +var counter = require('component-counter.js'); +var gpg = require('component-gpg-ex.js'); + +var URLEncoder = java.net.URLEncoder; + +var DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'; + +var gpgEncryptedAuthToken = {/**LINES +-----BEGIN PGP MESSAGE----- +Comment: GPGTools - https://gpgtools.org + +hQEMAwpgonLPA1NTAQf+MowR8XeAd6jtJhHE6s8FwmXyYEI1R8J3kEo+XBnUWXph +dVQYHUAj+lWl9Pd8YpJmImT+Qf9mseZSi0wbkUi6N1UJogwtx4sAu9szvLcEhYa2 +68Oyl+AY8jdn608OKqXRwG8z4HVrzdFgyEBuyJ/GafDH+bXcLYNtROcb63FlMlhJ +zLymaJD85W3uKlmYqJ0/OHLxn+fruRvZz0ZxlN1w3lj8t0wqLk+cOcTVMZkpdiYD +BGj8fkS/OTQBBNACmsCJDoUdBEMSRpjU3z55Zn5EGK0R3uTkZfuo+pJjGaZEtz8m +kuM0Yxyvq38fzPC9zrGQKsyXBOH3B8/x7GqcNDEVRtJnAWDu4syv3FkiGAzyHiKZ +nEupU97rz+XL5fKU89i6+ttAAC+xIMkASAde/Z5CdOdGjwfjx3u7U+c8XmaAcQtE +ibIucc2d0dsCkynzket0EfqExEXj4NUqxmwIS118vKMZAwap3FnaxQ== +=fjt8 +-----END PGP MESSAGE----- +*/}; + +var SITE_PROXY_MAP = { + "hatterink": "https://hatter.ink/pget.action?__auth_token={auth_token}&target={target}" +}; + +var main = () => { + var args = argsEx.parseDefARGs(['s', 'slient', 'S', 'skip-cert']); + + var urllist = args.val('u', 'urllist'); + var prefix = args.val('prefix'); + var suffix = args.val('suffix'); + + if ((urllist == null) && (args.length < 1)) { + println('get.js [FLAGS] []'); + println(' -u, --urllist URL List'); + println(' --prefix File prefix when using URL List'); + println(' --suffix File suffix when using URL List'); + println(' -s, --slient Slient mode'); + println(' -S, --skip-cert Skip cert check'); + println(' --agent User agent'); + println(' -p, --proxy Site, hatterink') + return; + } + + if (urllist == null) { + downlaodURL(args, args[0], (args.length > 1)? args[1]: null); + } else { + var fl = __.rfile.from(urllist); + if (fl.notExists()) { + println('File list not exists: ' + urllist); + return; + } + var list = $ARRAY(fl.list()).filter((u) => { + return u.trim() != ''; + }); + list.forEach((u, i) => { + println('Processing ' + i + ' of ' + list.length + ':'); + if ((prefix == null) && (suffix == null)) { + downlaodURL(args, u); + } else { + downlaodURL(args, u, (prefix || '') + $$.numFormat('0000').format(i) + (suffix || '')); + } + }); + } +}; + +var downlaodURL = (args, url, fn) => { + var slient = args.flg('s', 'slient'); + var skipCert = args.flg('S', 'skip-cert'); + var agent = args.val('agent'); + if (!/^http(s)?:\/\/.*/.test(url.toLowerCase())) { + println('URL should starts with http:// or https://'); + return; + } + if (fn == null) { + var u = (url.contains('?')) ? url.substring(0, url.indexOf('?')) : url; + fn = URLEncoder.encode((u.contains('/')) ? u.substring(u.lastIndexOf('/') + 1) : u, 'UTF-8') || ('unknown-' + $$.date().millis()); + } + + var readlUrl = url; + var proxy = args.val('p', 'proxy'); + if (proxy != null) { + var proxyUrl = SITE_PROXY_MAP[proxy]; + if (proxyUrl == null) { + xprintln('[WARN] Unknown proxy: ' + proxy); + } else { + xprintln('[INFO] Using proxy: ' + proxy); + var authToken = gpg.decryptArmor(gpgEncryptedAuthToken); + readlUrl = proxyUrl.replace('{auth_token}', authToken).replace('{target}', encodeURIComponent(url)); + } + } + + if (!slient) { println('GET ' + url + ' -> ' + fn); } + var fos = new java.io.FileOutputStream(fn); + var len = $$.httpRequest() + .url(readlUrl) + .skipCertCheck(skipCert) + .addHeader('User-Agent', agent || DEFAULT_USER_AGENT) + .get(fos, (slient ? null : counter.getCounter2Bar())); + fos.close(); + if (!slient) { println(); } + if (!slient) { println('File download finished, downloaded bytes: ' + bytes.showBytes(len)); } +}; + +main(); diff --git a/scripts/gitbook.js b/scripts/gitbook.js new file mode 100644 index 0000000..d78b944 --- /dev/null +++ b/scripts/gitbook.js @@ -0,0 +1,201 @@ +#! /usr/bin/env runjs + +var ByteArrayOutputStream = java.io.ByteArrayOutputStream; +var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes; +var FileUtil = Packages.me.hatter.tools.commons.file.FileUtil; + +var argsjs = require('component-args.js'); + +var CALIBRE_HOME = '/Applications/calibre.app/Contents/MacOS'; + +var DOT = 'dot'; +var NPM = 'npm'; +var GITBOOK = 'gitbook'; +var CALIBRE_EBOOK_CONVERT = 'ebook-convert'; + +var NODE_INSTALL_URL = 'https://nodejs.org/en/download/'; +var CALIBRE_INSTALL_URL = 'https://calibre-ebook.com/download'; + +var DOT_INSTALL = 'brew install graphviz'; +var GITBOOK_INSTALL = 'npm install -g gitbook-cli'; + +var DEFAULT_PROCESSOR_VIZ = null; +var DEFAULT_PROCESSOR = { + 'plantuml': (lns, tmpDir) => { + $ONCE('gitbook.js-defaultprocessor-plantuml-requirejar-plantuml').run(() => { + requireJAR('plantuml-8059.jar'); + }); + var FileFormat = Packages.net.sourceforge.plantuml.FileFormat; + var FileFormatOption = Packages.net.sourceforge.plantuml.FileFormatOption; + var SourceStringReader = Packages.net.sourceforge.plantuml.SourceStringReader; + + var puml = $ARR(lns).join('\n'); + var dgst = Bytes.from(puml).digest($$.digests().sha256()).asHex(); + var baos = new ByteArrayOutputStream(); + var reader = new SourceStringReader(puml); + reader.generateImage(baos, new FileFormatOption(FileFormat.PNG, false)); + $$.rFile(tmpDir, dgst + '.png').write(baos.toByteArray()); + return ''; + }, + 'graphviz': (lns, tmpDir) => { + var viz = $ARR(lns).join('\n'); + var vizB64 = Bytes.from(viz).asBase64(); + var dgst = Bytes.from(viz).digest($$.digests().sha256()).asHex(); + var vizToPngRes = $$.shell().commands('sh', '-c', 'echo ' + vizB64 + ' | base64 -D | dot -Tpng').start(); + $$.rFile(tmpDir, dgst + '.png').write(vizToPngRes[0].bytes()); + return ''; + } +}; + +// return null or string +var dealWithMarkdown = (f, tmpDir, mdList, plugins) => { + var list = []; + var codeTag = null; + var codeList = []; + var inCode = false; + $ARR(mdList).forEach((ln) => { + if (inCode) { + if ($STR(ln.trim()) == '```') { + // CODE ENDED + inCode = false; + var plugInFunc = null; + plugins.forEach((p) => { + if (plugInFunc == null) { + plugInFunc = p[codeTag || 'default']; + } + }); + if (plugInFunc == null) { + // plugin not found + list.push('```' + codeTag); + codeList.forEach((ln) => { list.push(ln) } ); + list.push('```'); + } else { + list.push(plugInFunc(codeList, tmpDir)); + } + } else { + codeList.push(ln); + } + } else if (ln.trim().startsWith('```')) { + // CODE STARTED + inCode = true; + codeList = []; + codeTag = ln.trim().substring(3).trim(); + } else { + list.push(ln); + } + }); + if (inCode) { + xprintln('[ERROR] Markdown content error: ' + f); + return null; + } + return list.join('\n'); +}; + +// gitbook-cli OR https://github.com/GitbookIO/gitbook-pdf ? +var main = () => { + var args = argsjs.parseDefARGs(['default-processor', 'skip-delete-tmp']); + if (args.length < 1) { + xprintln('[ERROR] Need arguments.'); + xprintln(); + xprintln('gitbook.js [args] '); + xprintln(' --default-processor enable default processor'); + xprintln(' --skip-delete-tmp skip delete tmp dir'); + xprintln(' -p, --processor with file processor'); + xprintln(' -t, --type <"pdf"> default pdf'); + xprintln(' -d, --dir default "."'); + return; + } + + var whichRes = $$.shell().commands('which', NPM).start(); + if ($STR(whichRes[0].toString().trim()) == '') { + xprintln('[ERROR] Node is not installed.'); + xprintln('[INFO] Install node URL: ' + NODE_INSTALL_URL); + return; + } + xprintln('[OK] Check node installed: ' + $$.shell().commands('node', '-v').start()[0].toString().trim()); + var gitbookRes = $$.shell().commands('which', GITBOOK).start(); + if ($STR(gitbookRes[0].toString().trim()) == '') { + xprintln('[ERROR] Gitbook is not installed.'); + xprintln('[INFO] Install gitbook command: ' + GITBOOK_INSTALL); + return; + } + xprintln('[OK] Check gitbook installed: ' + $$.shell().commands('gitbook', '-V').start()[0].toString().trim().replace('\n', '; ')); + var dotRes = $$.shell().commands('which', DOT).start(); + if ($STR(dotRes[0].toString().trim()) == '') { + xprintln('[ERROR] Graphviz is not installed.'); + xprintln('[INFO] Install graphviz command: ' + DOT_INSTALL); + return; + } + xprintln('[OK] Check graphviz installed: ' + $$.shell().commands('dot', '-V').mergeErrorOutput(true).start()[0].toString().trim().replace('\n', '; ')); + var ebookConvert = $$.file(CALIBRE_HOME, CALIBRE_EBOOK_CONVERT); + if (!(ebookConvert.exists())) { + xprintln('[ERROR] Calibre is not installed.'); + xprintln('[INFO] Install calibre URL: ' + CALIBRE_INSTALL_URL); + return; + } + xprintln('[OK] Check calibre installed: ' + $$.shell().commands(ebookConvert.getAbsolutePath(), '--version').start()[0].list().get(0)); + + var gitbookShell = $$.shell(); + var ebookConvertRes = $$.shell().commands('which', CALIBRE_EBOOK_CONVERT).start(); + if ($STR(ebookConvertRes[0].toString().trim()) == '') { + xprintln('[INFO] $PATH add calibre home: ' + CALIBRE_HOME); + gitbookShell.env('PATH', '$PATH:' + CALIBRE_HOME); + } + + var _type = args.val('t', 'type') || 'pdf'; + var _dir = args.val('d', 'dir') || '.'; + + if ($STR(_type) != 'pdf') { + xprintln('[ERROR] Currently only supports pdf.'); + return; + } + + var _tempDir = $$.file(_dir, '.tmp'); + var plugins = []; + var processors = args.vals('p', 'processor'); + processors.forEach((p) => { + xprintln('[INFO] Load processor: ' + p); + plugins.push(require('file://' + p)); + }); + if (args.flg('default-processor')) { + plugins.push(DEFAULT_PROCESSOR); + } + if (plugins.length > 0) { + if (_tempDir.exists()) { + xprintln('[INFO] Delete exists tmp dir: ' + _tempDir); + FileUtil.deleteDirectory(_tempDir); + } + xprintln('[INFO] Create tmp dir: ' + _tempDir); + _tempDir.mkdirs(); + $ARR($$.file(_dir).listFiles()).forEach((f) => { + if (f.getName().toLowerCase().endsWith('.md')) { + var contents = $$.rFile(f).list(); + var newContents = dealWithMarkdown(f, _tempDir, contents, plugins); + if (newContents != null) { + xprintln('[INFO] Update md file: ' + f.getName()); + $$.rFile(_tempDir, f.getName()).write(newContents); + } else { + $$.rFile(_tempDir, f.getName()).write(contents.join('\n')); + } + } + }); + } + + var commands = []; + commands.push(GITBOOK); + commands.push(_type); + commands.push((plugins.length > 0) ? _tempDir : _dir); + commands.push(args[0]); + + xprintln('[INFO] Run gitbook command: ' + $TO_JAVA_LIST(commands)); + gitbookShell.commands(commands).run(); + + if (_tempDir.exists()) { + if (!(args.flg('skip-delete-tmp'))) { + xprintln('[INFO] Delete tmp dir: ' + _tempDir); + FileUtil.deleteDirectory(_tempDir); + } + } +}; + +main(); diff --git a/scripts/hash.js b/scripts/hash.js new file mode 100644 index 0000000..cbc74c8 --- /dev/null +++ b/scripts/hash.js @@ -0,0 +1,26 @@ +#! /usr/bin/env runjs + +var main = () => { + var args = $ARRAY($ARGS); + if (args.length < 1) { + println('No args...'); + println(); + println('hash.js ') + return; + } + args.forEach((f) => { + var fi = $$.file(f); + if (fi.isDirectory()) { println('Skip directory: ' + fi); println(); return; } + println('Hashs for: ' + fi); + println('Length : ' + fi.length() + ' byte(s)'); + ['md5', 'sha1', 'sha256', 'sha384', 'sha512'].forEach((k) => { + var d = $$.digests()[k](); + var digest = $$.rFile(fi).digest(d); + println(repeat(' ', 6 - k.length) + k.toUpperCase() + ' : ' + digest.asHex()); + println(repeat(' ', 6) + ' : ' + digest.asBase64()); + }); + println(); + }); +}; + +main(); diff --git a/scripts/hatterserver.js b/scripts/hatterserver.js new file mode 100644 index 0000000..de2ea6c --- /dev/null +++ b/scripts/hatterserver.js @@ -0,0 +1,9 @@ +#! /usr/bin/env runjs + +requireJAR('hatterserver-1.0.jar'); + +var main = () => { + Packages.hatterserver.Launcher.main($ARGS); +}; + +main(); diff --git a/scripts/javacc5.js b/scripts/javacc5.js new file mode 100644 index 0000000..d3f0adf --- /dev/null +++ b/scripts/javacc5.js @@ -0,0 +1,50 @@ +#! /usr/bin/env runjs + +var OSUtil = Packages.me.hatter.tools.commons.os.OSUtil; + +//var argsjs = require('component-args.js'); +var osjs = require('component-os.js'); +var packagejs = require('component-package.js'); +var javahomejs = require('component-javahome.js'); +var filesystemjs = require('component-filesystem.js'); + +var JAVACC_PACKAGE_INFO = { + '5': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/javacc-5.0.zip', + //'package': 'https://playsecurity.org/getdoc/1749_C31883A04B509AF7E93BE382B37F7F88/javacc-5.0.zip', + 'sha256': '9a692fdd4ee1365da540054f4bb95e4852cf0216ce1b7ba54470365f5e52c8c7', + 'basePath': '~/.jssp/builder/javacc-5.0', + 'subPath': 'javacc-5.0', + 'bin': 'bin/javacc' + } +}; + +var main = () => { + + var javaHome = javahomejs.getJavaHome('1.7'); + if (javaHome == null) { javaHome = javahomejs.getJavaHome('1.8'); } + if (javaHome == null) { javaHome = javahomejs.getJavaHome('9.0'); } + if (javaHome == null) { + xprintln('[WARN] Cannot find java, use system Java.'); + } + + xprintln('[INFO] Get JavaCC local package info.'); + var javaccLocalPackage = packagejs.getLocalPackage(JAVACC_PACKAGE_INFO['5'], true); + + var commandArgs = []; + var buildCommands = []; + buildCommands.push(javaccLocalPackage.binFile); + $ARR($ARGS).forEach((a) => { buildCommands.push(a); commandArgs.push(a); }); + + xprintln('[INFO] JAVA_HOME = ' + (javaHome || crender('[GREEN]@system'))); + xprintln('[INFO] JAVACC_HOME = ' + javaccLocalPackage.packageHome); + xprintln('[INFO] ARGUMENTS = ' + $ARR(commandArgs).toJavaList()); + + var sh = $$.shell(true); + if (javaHome != null) { + sh.env('JAVA_HOME', javaHome).env('PATH', javaHome + '/bin:' + $$.env('PATH')); + } + sh.commands(buildCommands).run(); +}; + +main(); diff --git a/scripts/javadoc.js b/scripts/javadoc.js new file mode 100644 index 0000000..967ef92 --- /dev/null +++ b/scripts/javadoc.js @@ -0,0 +1,50 @@ +#! /usr/bin/env runjs + +var FastJSON = Packages.com.alibaba.fastjson.JSON; + +var main = () => { + var javadocConfigFile = __.rfile.from('javadoc.json'); + if (javadocConfigFile.notExists()) { + xprintln('[WARN] file `javadoc.json` not found!'); + println(); + println('Sample JSON:'); + + println(FastJSON.toJSONString($$.parseJSON(JSON.stringify({ + "dest": "", + "source": "", + "subpackages": [ + "com.example.a", + "com.example.b" + ], + "encoding": "utf-8", + "charset": "utf-8" + })), true).replaceAll('\t', ' ')); + return; + } + var javadocConfig = JSON.parse(javadocConfigFile.string()); + var cmds = []; + cmds.push('javadoc'); + if (javadocConfig.dest) { + cmds.push('-d'); + cmds.push(javadocConfig.dest); + } + if (javadocConfig.source) { + cmds.push('-sourcepath'); + cmds.push(javadocConfig.source); + } + if (javadocConfig.subpackages) { + cmds.push('-subpackages'); + cmds.push(javadocConfig.subpackages.join(':')); + } + cmds.push('-encoding'); + cmds.push(javadocConfig.encoding || 'utf-8'); + cmds.push('-charset'); + cmds.push(javadocConfig.charset || 'utf-8'); + + xprintln('[INFO] Command: ' + cmds.join(' ')); + + $$.shell(true).commands(cmds).run(); +}; + +main(); + diff --git a/scripts/konanc.js b/scripts/konanc.js new file mode 100644 index 0000000..1418a11 --- /dev/null +++ b/scripts/konanc.js @@ -0,0 +1,71 @@ +#! /usr/bin/env runjs + +var OSUtil = Packages.me.hatter.tools.commons.os.OSUtil; + +//var argsjs = require('component-args.js'); +var osjs = require('component-os.js'); +var packagejs = require('component-package.js'); +var javahomejs = require('component-javahome.js'); +var filesystemjs = require('component-filesystem.js'); + +var KONANC_PACKAGE_INFO = { + 'macOS': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/kotlin-native-macos-0.5.tar.gz', + //'package': 'https://playsecurity.org/getdoc/1745_9CAC8D9CD48CE2362D7910AA09627555/kotlin-native-macos-0.5.tar.gz', + 'sha256': '73dcaebb924b8597e71561e2b9027e64355fd08a0c3b28e055e550550f03cad2', + 'basePath': '~/.jssp/builder/kotlin-native-macos-0.5', + 'subPath': 'kotlin-native-macos-0.5', + 'bin': 'bin/konanc' + }, + 'Linux': { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/kotlin-native-linux-0.5.tar.gz', + //'package': 'https://playsecurity.org/getdoc/1744_BA86D28143757D90507E80BD823392AB/kotlin-native-linux-0.5.tar.gz', + 'sha256': '6c5630c3ba6104d263e3947f12bf975efaf54fd95d74db4bd2df1d211cead9e4', + 'basePath': '~/.jssp/builder/kotlin-native-linux-0.5', + 'subPath': 'kotlin-native-linux-0.5', + 'bin': 'bin/konanc' + } +}; + +var main = () => { + if (osjs.getOS().arch != 'x86_64') { + xprintln('[ERROR] Only suports x86_64!'); + return; + } + + var javaHome = javahomejs.getJavaHome('1.8'); + if (javaHome == null) { javaHome = javahomejs.getJavaHome('9.0'); } + if (javaHome == null) { + xprintln('[WARN] Cannot find java, use system Java.'); + } + + var packageInfo; + if (OSUtil.isMacOS()) { + packageInfo = KONANC_PACKAGE_INFO.macOS; + } else if (OSUtil.isLinux()) { + packageInfo = KONANC_PACKAGE_INFO.Linux; + } else { + xprintln('[ERROR] Only supports macOS and Linux.'); + return; + } + + xprintln('[INFO] Get konanc local package info.'); + var konancLocalPackage = packagejs.getLocalPackage(packageInfo, true); + + var commandArgs = []; + var buildCommands = []; + buildCommands.push(konancLocalPackage.binFile); + $ARR($ARGS).forEach((a) => { buildCommands.push(a); commandArgs.push(a); }); + + xprintln('[INFO] JAVA_HOME = ' + (javaHome || crender('[GREEN]@system'))); + xprintln('[INFO] KONANC_HOME = ' + konancLocalPackage.packageHome); + xprintln('[INFO] ARGUMENTS = ' + $ARR(commandArgs).toJavaList()); + + var sh = $$.shell(true); + if (javaHome != null) { + sh.env('JAVA_HOME', javaHome).env('PATH', javaHome + '/bin:' + $$.env('PATH')); + } + sh.commands(buildCommands).run(); +}; + +main(); diff --git a/scripts/m3u8download.js b/scripts/m3u8download.js new file mode 100644 index 0000000..22c12c5 --- /dev/null +++ b/scripts/m3u8download.js @@ -0,0 +1,77 @@ +#! /usr/bin/env runjs + +var bytes = require('component-bytes.js'); +var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil; + +var getM3u8AsList = (fn) => { + var m3u8FileContents; + if (/^https?:\/\/.*/i.test(fn)) { + println('Download m3u8 file: ' + fn); + m3u8FileContents = IOUtil.readToList($$.httpRequest().url(fn).get()); + } else { + if (!$$.file(fn).exists()) { + println('M3U8 file not extists: ' + fn); + return; + } + m3u8FileContents = $$.rFile(fn).list(); + } + return m3u8FileContents; +}; + +// http://youku.online-downloader.com/ +var main = () => { + if ($ARGS.length < 1) { + println('No args!'); + return; + } + + var m3u8FileContents = getM3u8AsList($ARGS[0]); + + var index = 0; + var tsList = []; + + var totalMillis = 0; + var totalLength = 0; + var totalTsCount = 0; + m3u8FileContents.forEach((x) => { if ((/^https?:\/\/.*/.test(x))) { totalTsCount++; } }); + m3u8FileContents.forEach((x) => { + if (!(/^https?:\/\/.*/.test(x))) { + // SKIP + return; + } + index++; + var tsFileFn = repeat('0', 5 - $STR(index).length) + index + '.ts'; + tsList.push(tsFileFn); + println('File: ' + x + " --> " + tsFileFn + ' (' + index + '/' + totalTsCount + ')'); + + print('-- Downloading: '); + var tsFile = new java.io.File(tsFileFn); + if (tsFile.exists()) { + println('EXISTS!'); + } else { + var _s = $$.date().millis(); + var _len = 0; + var fos = new java.io.FileOutputStream(tsFile); + $$.httpRequest() + .url(x) + .addHeader('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36') + .get(fos, (x) => { print('.'); _len += x; }); + fos.close(); + var _e = $$.date().millis(); + totalMillis += _e - _s; + totalLength += _len; + println(', filesize: ' + bytes.showBytes(_len) + ', speed: ' + bytes.showBytes((_len * 1000) / (_e - _s)) + '/s'); + } + }); + println('Join ts files...'); + var cmdFile = $$.file('_temp_merge_ts'); + var newFileName = new Date().getTime() + '.mp4' + $$.rFile(cmdFile).write('ffmpeg -i "concat:' + tsList.join('|') + '" -c copy -bsf:a aac_adtstoasc ' + newFileName); + $$.shell().inheritIO().commands('sh', '_temp_merge_ts').run(); + cmdFile.delete(); + + println(); + println('Finished, download video file is: ' + newFileName + ', filesize: ' + bytes.showBytes(totalLength) + ', speed: ' + bytes.showBytes((totalLength * 1000) / totalMillis) + '/s'); +}; + +main(); diff --git a/scripts/macostool.js b/scripts/macostool.js new file mode 100644 index 0000000..739cbee --- /dev/null +++ b/scripts/macostool.js @@ -0,0 +1,79 @@ +#! /usr/bin/env runjs + +var args = require('component-args.js'); + +var printHelp = () => { + println('macostool.js cmd'); + println('help Print help'); + println('list-java Print java list') + println('list-network Print network devices'); + println('listen-tcp Print TCP listen'); + println('listen-udp Print UDP listen'); + println('wifi-info Print WIFI info'); + println('wifi-scan Print WIFI scan'); + println('print-route Print route list'); + println('install-brew Install brew'); + println('install-jenv Install jenv') + println('install-ports Install MacPorts'); + println('install-sdkman Install SDKMAN'); + println('install-dart Install Dart'); +}; + +var main = () => { + var parsedArgs = args.parseARGS(); + if (parsedArgs.args.length == 0) { + printHelp(); + return; + } + + var commands = { + 'listen-tcp': () => { // ==OR== netstat -Waltn | grep LISTEN + $$.shell().inheritIO().commands('lsof', '-iTCP', '-sTCP:LISTEN', '-n', '-P').run(); + }, + 'listen-udp': () => { + $$.shell().inheritIO().commands('lsof', '-iUDP', '-P', '-n').run(); + }, + 'wifi-info': () => { + $$.shell().inheritIO().commands('/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I').run(); + }, + 'wifi-scan': () => { + $$.shell().inheritIO().commands('/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-s').run(); + }, + 'list-java': () => { + $$.shell().inheritIO().commands('/usr/libexec/java_home', '-V').run(); + }, + 'list-network': () => { + $$.shell().inheritIO().commands('networksetup', '-listallhardwareports').run(); + }, + 'print-route': () => { + $$.shell().inheritIO().commands('netstat', '-nr').run(); + }, + 'install-brew': () => { + $$.shell().inheritIO().commands('/usr/bin/ruby', '-e', '"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"').run(); + }, + 'install-jenv': () => { + $$.shell().inheritIO().commands('sh', '-c', 'curl -L -s get.jenv.io | bash').run(); + }, + 'install-ports': () => { + println('Please access: https://www.macports.org/install.php'); + }, + 'install-sdkman': () => { + $$.shell().inheritIO().commands('sh', '-c', 'curl -s "https://get.sdkman.io" | bash').run(); + }, + 'install-dart': () => { + // https://www.dartlang.org/install/mac + println('$ brew tap dart-lang/dart'); + println('$ brew install dart'); + } + }; + var nullCommand = (cmd) => { + println('[ERROR] Command not found: ' + cmd); + println(); + printHelp(); + }; + + (commands[parsedArgs.args[0]] || nullCommand)(parsedArgs.args[0]); +}; + +main(); + diff --git a/scripts/makepassword.js b/scripts/makepassword.js new file mode 100644 index 0000000..6c959ed --- /dev/null +++ b/scripts/makepassword.js @@ -0,0 +1,43 @@ +#! /usr/bin/env runjs + +var UnixArgsUtil = Packages.me.hatter.tools.commons.args.UnixArgsUtil; + +var main = () => { + UnixArgsUtil.parseGlobalArgs($ARGS); + + if (UnixArgsUtil.ARGS.flags().containsAny('h', 'help')) { + println('Make password from secure random, usage:'); + println(' makepassword.js'); + println(' h|help Help'); + println(' l|len|length Password length in bytes (default 10)'); + println(' c|cnt|count Password count (default 1)'); + println(' e|ecn|encode Password encoding(base32, base58, base64, hex) (default base58)'); + return; + } + + var len = UnixArgsUtil.ARGS.kvalueAny('l', 'len', 'length') || 10; + var cnt = UnixArgsUtil.ARGS.kvalueAny('c', 'cnt', 'count') || 1; + var enc = $STR(UnixArgsUtil.ARGS.kvalueAny('e', 'enc', 'encode') || 'base58').toLowerCase(); + + var isNotSupportedEnc = false; + var random = $$.secureRandom(); + (parseInt(cnt)).times(() => { + var passwdBs = random.nextBytes(len); + if (['32', 'b32', 'base32'].contains(enc)) { + println($$.io().bytes(passwdBs).asBase32()); + } else if (['58', 'b58', 'base58'].contains(enc)) { + println($$.io().bytes(passwdBs).asBase58()); + } else if (['64', 'b64', 'base64'].contains(enc)) { + println($$.io().bytes(passwdBs).asBase64()); + } else if (['hex'].contains(enc)) { + println($$.io().bytes(passwdBs).asHex()); + } else { + isNotSupportedEnc = true; + } + }); + if (isNotSupportedEnc) { + println('Not supported encode: ' + enc); + } +}; + +main(); diff --git a/scripts/makeself.js b/scripts/makeself.js new file mode 100644 index 0000000..608c052 --- /dev/null +++ b/scripts/makeself.js @@ -0,0 +1,96 @@ +#! /usr/bin/env runjs + +var argsjs = require('component-args.js'); +var packagejs = require('component-package.js'); +var filesystemjs = require('component-filesystem.js'); + +var MAKESELF_PACKAGE_INFO = { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/makeself-2.4.0.tar.gz', + //'package': 'https://playsecurity.org/getdoc/2552_C2AE09CBA9C18B4B9E5472E0C2304C74/makeself-2.4.0.tar.gz', + 'sha256': '76a8c3f3fad1b55c39ba2904a19e74962151f9481df03091d4e54938bdd13f50', + 'basePath': '~/.jssp/builder/makeself-2.4.0', + 'subPath': 'makeself-release-2.4.0', + 'bin': 'makeself.sh' +}; +var MAKESELF_PACKAGE_INFO_v230 = { + 'package': 'https://publicbucket-1251781687.coscd.myqcloud.com/makeself-2.3.0.tar.gz', + //'package': 'https://playsecurity.org/getdoc/1628_C2F12AFBC92C8A19A2E914B457AD053E/makeself-2.3.0.tar.gz', + 'sha256': '87385ed878938c4cd6907d1401ec6ba5bee2224fb97f7865a11e617bf94d4a0b', + 'basePath': '~/.jssp/builder/makeself-2.3.0', + 'subPath': 'makeself-2.3.0', + 'bin': 'makeself.sh' +}; + +var sampleMakeselfJSON = { + "files": [ + "file1.txt", + "file2.txt" + ], + "target": { + "options": [ "--sha256" ], // https://makeself.io/ + "fileName": "sample.sh", + "label": "sample label", + "startupScript": "./startup.sh", + "startupScriptArgs": [] + } +}; + +var main = () => { + var args = argsjs.parseDefARGs(); + + var makeself = $$.file(args.val('c', 'config') || 'makeself.json'); + if (!(makeself.exists())) { + xprintln('[ERROR] Cannot find file `makeself.json`.'); + xprintln('[INFO] Sample: ' + $$.stringify($$.parseJSON(JSON.stringify(sampleMakeselfJSON)), true)); + return; + } + var makeselfJSON = JSON.parse($$.rFile(makeself).string()); + + xprintln('[INFO] Get makeself.sh local package info.'); + var makeselfLocalPackage = packagejs.getLocalPackage(MAKESELF_PACKAGE_INFO, true); + + xprintln('[INFO] Check local temp dir: .makeself_js_temp_dir'); + var tempPath = $$.file('.makeself_js_temp_dir'); + if (tempPath.exists()) { __.fileutil.deleteDirectory(tempPath); } + tempPath.mkdirs(); + + var abort = false; + makeselfJSON.files.forEach((fn) => { + if (abort) { return; } + var f = $$.file(fn); + if (!f.exists()) { + abort = true; + xprintln('[ERROR] File not exists: ' + fn); + return; + } + xprintln('[INFO] Copy file: ' + fn); + __.ioutil.copyFile(f, $$.file(tempPath, f.getName())); + + if ((makeselfJSON.target.startupScript == $STR(f.getName())) || (makeselfJSON.target.startupScript == $STR('./' + f.getName()))) { + xprintln('[INFO] Set file executable: ' + fn); + filesystemjs.chmodAddExec($$.file(tempPath, f.getName())); + } + }); + if (abort) { return; } + + if (makeselfJSON.target == null) { makeselfJSON.target = {}; } + var makeselfCommands = [ makeselfLocalPackage.binFile.getAbsolutePath() ]; + if (makeselfJSON.target.options) { + makeselfCommands = makeselfCommands.concat(makeselfJSON.target.options); + } + makeselfCommands = makeselfCommands.concat(['.makeself_js_temp_dir', + makeselfJSON.target.fileName || 'unnamed.sh', + makeselfJSON.target.label || '', + makeselfJSON.target.startupScript + ]); + if (makeselfJSON.target.startupScriptArgs) { + makeselfJSON.target.startupScriptArgs.forEach((a) => { makeselfCommands.push(a); }); + } + + $$.shell().inheritIO().commands(makeselfCommands).run(); + + xprintln('[INFO] Clean up local temp dir: .makeself_js_temp_dir'); + if (tempPath.exists()) { __.fileutil.deleteDirectory(tempPath); } +}; + +main(); diff --git a/scripts/mapdownload.js b/scripts/mapdownload.js new file mode 100644 index 0000000..ae8dd55 --- /dev/null +++ b/scripts/mapdownload.js @@ -0,0 +1,78 @@ +#! /usr/bin/env runjs + +function long2tile(lon, zoom) { + return (Math.floor((lon + 180) / 360 * Math.pow(2, zoom))); +} + +function lat2tile(lat, zoom) { + return (Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom))); +} + +main = () => { + if ($ARGS.length < 3) { + println("Usage: mapdownload.js pattern true|false zoom [png|jpg]"); + println(" | | | |"); + println(" +-------+----------+----+----------- URL Pattern"); + println(" | | |"); + println(" +----------+----+----------- Reverse Y (Gaode -> TMS should set true)"); + println(" | |"); + println(" +----+----------- Zoom (0~20), 2_120,30~121,31"); + println(" |"); + println(" +----------- Image type"); + return; + } + + var pattern = $ARGS[0]; + var reverseY = "true".equals($ARGS[1]); + var z = $ARGS[2]; + var suffix = ($ARGS.length > 3) ? $ARGS[3] : 'png'; + + if (z.indexOf('_') < 0) { + var x_min = 0; + var y_min = 0; + var x_max = Math.pow(2, z) - 1; + var y_max = Math.pow(2, z) - 1; + } else { + var _z = z; + z = parseInt(_z.substring(0, _z.indexOf('_'))); + var lngLats = _z.substring(_z.indexOf('_') + 1).split('~'); + var lngLat1 = lngLats[0].split(','); + var lngLat2 = lngLats[1].split(','); + var x1 = long2tile(parseFloat(lngLat1[0]), z); + var x2 = long2tile(parseFloat(lngLat2[0]), z); + var y1 = lat2tile(parseFloat(lngLat1[1]), z); + var y2 = lat2tile(parseFloat(lngLat2[1]), z); + + x_min = Math.min(x1, x2); + x_max = Math.max(x1, x2); + y_min = Math.min(y1, y2); + y_max = Math.max(y1, y2); + } + + println('X, min: ' + x_min + ', max: ' + x_max); + println('Y, min: ' + y_min + ', max: ' + y_max); + + var count = 0; + var total = (x_max - x_min + 1) * (y_max - y_min + 1); + for (var x = x_min; x <= x_max; x++) { + for (var y = y_min; y <= y_max; y++) { + count++; + var url = pattern; + url = url.replace(/\{x\}/g, "" + x); + url = url.replace(/\{y\}/g, "" + y); + url = url.replace(/\{z\}/g, "" + z); + + var fiPath = $$.file("" + z, "" + x); + fiPath.mkdirs(); + var fi = $$.file(fiPath, (reverseY ? (Math.pow(2, z) - 1 - y) : y) + "." + suffix); + if (!fi.exists()) { + println("Downloading: " + url + " ==> " + fi + " (" + count + "/" + total + ")"); + var bs = $$.httpRequest().url(url).get().getBytes(); + $$.rFile(fi).write(bs); + } + } + } +}; + +main(); + diff --git a/scripts/markdownconvert.js b/scripts/markdownconvert.js new file mode 100644 index 0000000..ed6bad8 --- /dev/null +++ b/scripts/markdownconvert.js @@ -0,0 +1,108 @@ +#! /usr/bin/env runjs + +requireJAR('markdown4j-2.2.jar'); + +var argsjs = require('component-args.js'); +var counterjs = require('component-counter.js'); + +var File = java.io.File; +var FileUtil = Packages.me.hatter.tools.commons.file.FileUtil; +var Markdown4jProcessor = Packages.org.markdown4j.Markdown4jProcessor; + +var BOOTSTRAP = 'https://playsecurity.org/css/bootstrap.css'; +var BOOTSTRAP_THEME = 'https://playsecurity.org/css/bootstrap-theme.css'; + +var main = () => { + var args = argsjs.parseDefARGs(); + if (args.length < 1) { + xprintln('[ERROR] Need arguments.'); + xprintln(); + xprintln('markdownconvert.js [output.htm|output.pdf]'); + xprintln(); + xprintln(' -t, --title [PDF] Title'); + //xprintln(' --author [PDF] Author') + return; + } + + var mdFile = $$.file(args[0]); + if (!mdFile.exists()) { + xprintln('[ERROR] File not exists: ' + mdFile); + return; + } + + xprintln('[INFO] Make tmp dir: .tmp') + var tmpDir = $$.file('.tmp'); + tmpDir.mkdirs(); + + if (!$$.file(tmpDir, 'bootstrap.css').exists()) { + print('[INFO] Download file: bootstrap.css'); + var fos = new java.io.FileOutputStream($$.file(tmpDir, 'bootstrap.css')); + $$.httpRequest().skipCertCheck().url(BOOTSTRAP).get(fos, counterjs.getCounter()); + fos.close(); + println(); + } + if (!$$.file(tmpDir, 'bootstrap-theme.css').exists()) { + print('[INFO] Download file: bootstrap-theme.css'); + var fos = new java.io.FileOutputStream($$.file(tmpDir, 'bootstrap-theme.css')); + $$.httpRequest().skipCertCheck().url(BOOTSTRAP_THEME).get(fos, counterjs.getCounter()); + fos.close(); + println(); + } + + var isPDF = false; + var targetFile = (args.length > 1) ? $$.file(args[1]) : $$.file(mdFile.getAbsoluteFile().getParentFile(), mdFile.getName() + '.pdf'); + if (targetFile.getName().toLowerCase().endsWith('.pdf')) { + isPDF = true; + } + var htmlFile = (isPDF) ? $$.file('.tmp.htm') : targetFile; + + xprintln('[INFO] Render markdown file to html file: ' + htmlFile.getName()); + var md = $$.rFile(mdFile).string(); + var html = new Markdown4jProcessor().process(md); + html = '\n' + + '\n' + + '\n' + + '\n' + + '\n' + + '\n' + + '\n\n\n' + html + '\n\n\n\n' + + '\n'; + $$.rFile(htmlFile).write(html); + + if (isPDF) { + xprintln('[INFO] Render html file to pdf file: ' + targetFile.getName()); + var title = (args.val('t', 'title') || targetFile.getName()).replace('"', '\\"'); + // https://manual.calibre-ebook.com/conversion.html + $$.shell().commands('sh', '-c', + 'ebook-convert ' + + htmlFile.getAbsolutePath() + + ' ' + targetFile.getAbsolutePath() + + ' --title="' + title + '" --comments="" --language="en"' + //+ '--authors="' + (args.val('author') || $$.env('USER')) + '"' + + ' --book-producer="markdownconvert.js" --publisher="markdownconvert.js"' + //+ ' --chapter="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter \')]"' + // DEFAULT: //*[((name()='h1' or name()='h2') and re:test(., 'chapter|book|section|part\s+', 'i')) or @class = 'chapter'] + + ' --chapter="//*[(name()=\'h2\') or @class = \'chapter\']"' + + ' --chapter-mark="pagebreak" --page-breaks-before="/"' + + ' --level1-toc="//*[(name()=\'h3\') or @class = \'section\']"' + //+ ' --level1-toc="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter-1 \')]"' + //+ ' --level2-toc="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter-2 \')]"' + //+ ' --level3-toc="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter-3 \')]"' + //+ ' --no-chapters-in-toc' + //+ ' --pdf-add-toc' + + ' --max-levels="1" --breadth-first' + + ' --margin-left="62" --margin-right="62" --margin-top="56" --margin-bottom="56"' + + ' --pdf-default-font-size="12" --pdf-mono-font-size="12"' + + ' --paper-size="a4"' + + ' --pdf-header-template="

_TITLE_

"' + + ' --pdf-footer-template="

_SECTION_ _PAGENUM_

"') + .run(); + + xprintln('[INFO] Clean up tmp files.'); + htmlFile.delete(); + FileUtil.deleteDirectory(tmpDir); + } +}; + +main(); + diff --git a/scripts/markdowndocs.js b/scripts/markdowndocs.js new file mode 100644 index 0000000..1c9e2ff --- /dev/null +++ b/scripts/markdowndocs.js @@ -0,0 +1,17 @@ +#! /usr/bin/env runjs +var System = java.lang.System; +var LogUtil = Packages.me.hatter.tools.commons.log.LogUtil; +var LogType = Packages.me.hatter.tools.commons.log.LogUtil.LogType; + +LogUtil.setLogTypeSet($$.asList(LogType.ERROR, LogType.WARN, LogType.INFO, LogType.DEBUG, LogType.TRACE), true); + +requireJAR('maven:me.hatter:markdowndocsall:1.1'); + +var main = () => { + var Main = Packages.me.hatter.tools.markdowndocs.Main; + Main.main($ARGS); +}; + +main(); + + diff --git a/scripts/markdownpdf.js b/scripts/markdownpdf.js new file mode 100644 index 0000000..36a85dd --- /dev/null +++ b/scripts/markdownpdf.js @@ -0,0 +1,113 @@ +#! /usr/bin/env runjs + +// http://wkhtmltopdf.org/downloads.html +// $ wkhtmltopdf --user-style-sheet scripts/for-pdf.css --header-left "Hatter's Test Document - v1.0" +// --header-right '[page]/[toPage]' --header-line --margin-top 2.3cm --header-spacing 8 --header-font-size 10 +// --footer-line --footer-font-name 'Times New Roman' --footer-font-size 10 --footer-spacing 8 --margin-bottom 2.3cm +// --footer-center 'Copyright © 2017 Hatter Jiang. All Rights Reserved.' --debug-javascript test.htm test.pdf + +requireJAR('markdown4j-2.2.jar'); + +var File = java.io.File; +var RFile = Packages.me.hatter.tools.commons.io.RFile; +var StringUtil = Packages.me.hatter.tools.commons.string.StringUtil; +var Markdown4jProcessor = Packages.org.markdown4j.Markdown4jProcessor; + +var main = () => { + var whichResults = $$.shell().commands('which', 'wkhtmltopdf').start(); + if (!whichResults[0].toString().contains('wkhtmltopdf')) { + println('[ERROR] `wkhtmltopdf` must be installed ') + return; + } + if ($ARGS == null || $ARGS.length == 0) { + println('markdownpdf.js - Render markdown to pdf.') + println(); + println('ERROR: NO arguments assigned!'); + println('markdownpdf.js filename.md [filename.pdf]'); + return; + } + var mdFile = $$.file($ARGS[0]); + if (!mdFile.exists()) { + println('[ERROR] File not exists: ' + $ARGS[0]); + return; + } + + var pdfFile = ($ARGS.length > 1)? $ARGS[1]: (StringUtil.substringBeforeLast(mdFile.getName(), '.') || mdFile.getName()) + '.pdf'; + + var defaultMarkdownpdfConfig = { + "header-left": "Sample Document - v1.0", + "header-right": "[page]/[toPage]", + "header-line": true, + "margin-top": "2.3cm", + "header-spacing": "8", + "header-font-size": "10", + "footer-line": true, + "footer-font-name": "Times New Roman", + "footer-font-size": "10", + "footer-spacing": "8", + "margin-bottom": "2.3cm", + "footer-center": "Copyright © 2017 Hatter Jiang. All Rights Reserved.", + "debug-javascript": true + //"user-style-sheet": "pdf.css" + }; + var markdownpdfConfig = defaultMarkdownpdfConfig; + var fileMarkdownpdfConfig = $$.file('markdownpdf.json'); + if (fileMarkdownpdfConfig.exists()) { + println('[INFO] Config file markdownpdf.json found, load config.'); + markdownpdfConfig = JSON.parse(RFile.from(fileMarkdownpdfConfig).rReader().stringAndClose()); + } else { + println('[INFO] Config file markdownpdf.json not found, load default config.'); + } + + var boolConfigKeys = $$.set(); + boolConfigKeys.addAll($$.asList('header-line', 'footer-line', 'debug-javascript')); + + var cmds = $$.list(); + cmds.add('wkhtmltopdf'); + + ["header-left", "header-right", "header-line", "margin-top", "header-spacing", "header-font-size", "footer-line", + "footer-font-name", "footer-font-size", "footer-spacing", "margin-bottom", "footer-center", "debug-javascript", "user-style-sheet"].forEach((k) => { + var conf = (markdownpdfConfig[k] == null)? defaultMarkdownpdfConfig[k]: markdownpdfConfig[k]; + if (conf) { + cmds.add('--' + k); + if (!boolConfigKeys.contains(k)) { + cmds.add(conf); + } + } + }); + + println('[INFO] Render markdown file to temp html.') + var tempHtmlFile = File.createTempFile('markdowntopdf', '.html'); + tempHtmlFile.deleteOnExit(); + var md = RFile.from(mdFile).string(); + var html = new Markdown4jProcessor().process(md); + html = '\n' + + '\n' + + '\n' + + '\n' + + '\n' + + '\n\n\n' + html + '\n\n\n\n' + + '\n'; + RFile.from(tempHtmlFile).write(html); + + cmds.add(tempHtmlFile.getAbsolutePath()); + cmds.add(pdfFile); + println('[INFO] Execute command line: ' + cmds); + + var result = $$.shell().commands(cmds.toArray(java.lang.reflect.Array.newInstance($$.clazz('java.lang.String'), 0))).start(); + + println('[INFO] Outputs: ') + if (result[1] && result[1].toString().trim().length > 0) { + println(result[1].toString().trim()); + } + if (result[0].toString().trim().length > 0) { + println(result[0].toString().trim()); + } +}; + +main(); + diff --git a/scripts/markdownslide.js b/scripts/markdownslide.js new file mode 100644 index 0000000..e839b57 --- /dev/null +++ b/scripts/markdownslide.js @@ -0,0 +1,17 @@ +#! /usr/bin/env runjs +var System = java.lang.System; +var LogUtil = Packages.me.hatter.tools.commons.log.LogUtil; +var LogType = Packages.me.hatter.tools.commons.log.LogUtil.LogType; + +LogUtil.setLogTypeSet($$.asList(LogType.ERROR, LogType.WARN, LogType.INFO, LogType.DEBUG, LogType.TRACE), true); + +requireJAR('markdownslideall.jar'); + +var main = () => { + var Main = Packages.me.hatter.tools.markdownslide.Main; + Main.main($ARGS); +}; + +main(); + + diff --git a/scripts/mvnjar.js b/scripts/mvnjar.js new file mode 100644 index 0000000..9bd244f --- /dev/null +++ b/scripts/mvnjar.js @@ -0,0 +1,150 @@ +#! /usr/bin/env runjs + +var argsEx = require('component-args.js'); +var json = require('component-json-ex.js'); +var gpg = require('component-gpg-ex.js'); +var DefaultRollCounter = Packages.me.hatter.tools.commons.io.DefaultRollCounter; + +// need pom? +var REPO_BASEURLS = { + 'central': { + 'jar': 'https://search.maven.org/remotecontent?filepath={gid}/{aid}/{ver}/{aid}-{ver}.jar', + 'src': 'https://search.maven.org/remotecontent?filepath={gid}/{aid}/{ver}/{aid}-{ver}-sources.jar', + 'pom': 'https://search.maven.org/remotecontent?filepath={gid}/{aid}/{ver}/{aid}-{ver}.pom' + }, + 'aliyun_central': { + 'jar': 'https://maven.aliyun.com/repository/central/{gid}/{aid}/{ver}/{aid}-{ver}.jar', + 'src': 'https://maven.aliyun.com/repository/central/{gid}/{aid}/{ver}/{aid}-{ver}-sources.jar', + 'pom': 'https://maven.aliyun.com/repository/central/{gid}/{aid}/{ver}/{aid}-{ver}.pom' + } +}; + +var gpgEncryptedAuthToken = {/**LINES +-----BEGIN PGP MESSAGE----- +Comment: GPGTools - https://gpgtools.org + +hQEMAwpgonLPA1NTAQf+MowR8XeAd6jtJhHE6s8FwmXyYEI1R8J3kEo+XBnUWXph +dVQYHUAj+lWl9Pd8YpJmImT+Qf9mseZSi0wbkUi6N1UJogwtx4sAu9szvLcEhYa2 +68Oyl+AY8jdn608OKqXRwG8z4HVrzdFgyEBuyJ/GafDH+bXcLYNtROcb63FlMlhJ +zLymaJD85W3uKlmYqJ0/OHLxn+fruRvZz0ZxlN1w3lj8t0wqLk+cOcTVMZkpdiYD +BGj8fkS/OTQBBNACmsCJDoUdBEMSRpjU3z55Zn5EGK0R3uTkZfuo+pJjGaZEtz8m +kuM0Yxyvq38fzPC9zrGQKsyXBOH3B8/x7GqcNDEVRtJnAWDu4syv3FkiGAzyHiKZ +nEupU97rz+XL5fKU89i6+ttAAC+xIMkASAde/Z5CdOdGjwfjx3u7U+c8XmaAcQtE +ibIucc2d0dsCkynzket0EfqExEXj4NUqxmwIS118vKMZAwap3FnaxQ== +=fjt8 +-----END PGP MESSAGE----- +*/}; + +var SITE_PROXY_MAP = { + "hatterink": "https://hatter.ink/pget.action?__auth_token={auth_token}&target={target}" +}; + +var __cachec_authToken = null; + +var getRealUrl = (args, url) => { + var readlUrl = url; + var proxy = args.val('p', 'proxy'); + if (proxy != null) { + var proxyUrl = SITE_PROXY_MAP[proxy]; + if (proxyUrl == null) { + xprintln('[WARN] Unknown proxy: ' + proxy); + } else { + xprintln('[INFO] Using proxy: ' + proxy); + if (__cachec_authToken == null) { + __cachec_authToken = gpg.decryptArmor(gpgEncryptedAuthToken); + } + readlUrl = proxyUrl.replace('{auth_token}', __cachec_authToken).replace('{target}', encodeURIComponent(url)); + } + } + return readlUrl; +}; + +var main = () => { + var args = argsEx.parseDefARGs(['use-wget']); + if (args == null || (args.length != 1 && args.length != 3)) { + println('Usage:'); + println('mvnjar.js [--use-wget] [-r, --repo] [-p, --proxy] gid aid ver'); + println('mvnjar.js [--use-wget] [-r, --repo] [-p, --proxy] gid:aid:ver'); + println(' -r, --repo x(central), central, aliyun_central') + println(' -p, --proxy Site, hatterink') + return; + } + var repo = args.val('r', 'repo') + if (repo == null || repo == 'x') { repo = 'central'; } + + var gid, aid, ver; + if (args.length == 1) { + var splitedArgs1 = $STR(args[0]).split(':'); + if (splitedArgs1.length != 3) { + xprintln('[ERROR] Format error: ' + args[0]); + return; + } + gid = splitedArgs1[0]; + aid = splitedArgs1[1]; + ver = splitedArgs1[2]; + } else { + gid = args[0]; + aid = args[1]; + ver = args[2]; + } + + var baseUrls = REPO_BASEURLS[repo]; + if (baseUrls == null) { + xprintln('[ERROR] Repo not defined: ' + repo); + return; + } + var urlJar = baseUrls.jar; + var urlSrc = baseUrls.src; + var urlPom = baseUrls.pom; + + var uj = urlJar.replace(/{gid}/g, gid.replace(/\./g, '/')).replace(/{aid}/g, aid).replace(/{ver}/g, ver); + println('JAR: ' + uj); + if (args.flg('use-wget')) { + $$.shell().commands('wget', uj, '-O', aid + '-' + ver + '.jar').run(); + } else { + __.httprequest.fromUrl(getRealUrl(args, uj)).get(__.rfile.from(aid + '-' + ver + '.jar').file(), new DefaultRollCounter().prefix('Downloading ... ')); + } + + var hasSrc = true; + var us = urlSrc.replace(/{gid}/g, gid.replace(/\./g, '/')).replace(/{aid}/g, aid).replace(/{ver}/g, ver); + println('SRC: ' + us); + try { + if (args.flg('use-wget')) { + $$.shell().commands('wget', us, '-O', aid + '-' + ver + '-sources.jar').run(); + } else { + __.httprequest.fromUrl(getRealUrl(args, us)).get(__.rfile.from(aid + '-' + ver + '-sources.jar').file(), new DefaultRollCounter().prefix('Downloading ... ')); + } + } catch(e) { + hasSrc = false; + println('[WARN] download src failed.') + } + if (urlPom) { + var up = urlPom.replace(/{gid}/g, gid.replace(/\./g, '/')).replace(/{aid}/g, aid).replace(/{ver}/g, ver); + println('POM: ' + up); + if (args.flg('use-wget')) { + $$.shell().commands('wget', up, '-O', aid + '-' + ver + '-.pom').run(); + } else { + __.httprequest.fromUrl(getRealUrl(args, up)).get(__.rfile.from(aid + '-' + ver + '.pom').file(), new DefaultRollCounter().prefix('Downloading ... ')); + } + + } + + var b = { + repo: { + gid: gid, + aid: aid, + jar: aid + '-' + ver + '.jar', + pom: aid + '-' + ver + '.pom', + staticVersion: ver + } + }; + if (hasSrc) { + b.repo.src = aid + '-' + ver + '-sources.jar'; + } + var j = json.prettyJSON(b); + println(j); + __.rfile.from('build.json').write(j); + println('done') +}; + +main(); diff --git a/scripts/ossbackup.js b/scripts/ossbackup.js new file mode 100644 index 0000000..c853140 --- /dev/null +++ b/scripts/ossbackup.js @@ -0,0 +1,142 @@ +#! /usr/bin/env runjs + +requireJAR('aliyun-sdk-oss-2.4.1-SNAPSHOT.jar'); +requireJAR('commons-beanutils-1.8.0.jar'); +requireJAR('commons-codec-1.9.jar'); +requireJAR('commons-collections-3.2.1.jar'); +requireJAR('commons-lang-2.5.jar'); +requireJAR('commons-logging-1.2.jar'); +requireJAR('ezmorph-1.0.6.jar'); +requireJAR('hamcrest-core-1.1.jar'); +requireJAR('httpclient-4.4.1.jar'); +requireJAR('httpcore-4.4.1.jar'); +requireJAR('jdom-1.1.jar'); +requireJAR('json-lib-2.4-jdk15.jar'); + +var File = java.io.File; +var System = java.lang.System; +var FileInputStream = java.io.FileInputStream; +var FileOutputStream = java.io.FileOutputStream; + +var CounterInputStream = Packages.me.hatter.tools.commons.io.CounterInputStream; +var RFile = Packages.me.hatter.tools.commons.io.RFile; +var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil; + +var main = () => { + var start = $$.date().millis(); + + if ($ARGS.length == 0) { + println('Config file is not assigned.'); + return; + } + + var configJSON = null; + try { + var config = RFile.from($ARGS[0]).string(); + configJSON = JSON.parse(config); + } catch(e) { + println('Parse config error: ' + e); + } + + if (!configJSON || !configJSON.bucket || !configJSON.endpoint || !configJSON.accessKey || !configJSON.secretKey || !configJSON.backupFile) { + println('----- Config format -----'); + println('{'); + println(' \"endpoint\": \"\",'); + println(' \"accessKey\": \"\",'); + println(' \"secretKey\": \"\",'); + println(' \"bucket\": \"\",'); + println(' \"backupFile\": \"\",'); + println(' \"path\": \"default-backup-path\",'); + println(' \"limit\": \"10\",'); + println('}'); + return; + } + configJSON.path = configJSON.path || 'default-backup-path'; + configJSON.limit = configJSON.limit || 10; + + var OSSClient = Packages.com.aliyun.oss.OSSClient; + var ListObjectsRequest = Packages.com.aliyun.oss.model.ListObjectsRequest; + var client = new OSSClient(configJSON.endpoint, configJSON.accessKey, configJSON.secretKey); + try { + if (!client.doesBucketExist(configJSON.bucket)) { + println("Bucket NOT exists: " + configJSON.bucket); + return; + } + + var getCounter = (() => { + var total = 0; + var step = 1024 * 64; + return (len) => { + var t = total; + total += len; + var n = parseInt(total / step) - parseInt(t / step); + if (n > 0) { + for (var i = 0; i < n; i++) { + print('.'); + } + } + }; + }); + + var backupFiles = (configJSON.backupFile instanceof Array)? configJSON.backupFile: [configJSON.backupFile]; + + backupFiles.forEach((backupFile) => { + println('+++++ Start backup file: ' + backupFile + ' +++++'); + + var yyyyMMddHHmmss = $$.date().fmt('yyyyMMddHHmmss').format($$.date().today()); + var backupFileFile = new File(backupFile); + if (!backupFileFile.exists()) { + println("File not exists: " + backupFile); + return; // continue next file + } + + var fileName = backupFileFile.getName(); + var actualBackupFile = backupFile; + var actualBackupFileSuffix = ""; + if (configJSON.gpg && configJSON.gpg.keyId) { + var newFilePath = new File(System.getProperty("java.io.tmpdir"), fileName + '-' + yyyyMMddHHmmss + ".gpg").getAbsolutePath(); + actualBackupFile = newFilePath; + actualBackupFileSuffix = ".gpg"; + println("Encrypt file with GPG: " + newFilePath); + $$.shell().commands('sh', '-c', 'gpg -r ' + configJSON.gpg.keyId + ' -e -o "' + newFilePath + '" ' + backupFile).start(); + } + + println('Upload file: ' + backupFile + '-' + yyyyMMddHHmmss + actualBackupFileSuffix); + var databaseDbGpg = new FileInputStream(actualBackupFile); + var counterIS = new CounterInputStream(databaseDbGpg, getCounter()); + client.putObject(configJSON.bucket, configJSON.path + '/' + fileName + '-' + yyyyMMddHHmmss + actualBackupFileSuffix, counterIS); + println(); + + println('Clear OSS history files.'); + var objectListing = client.listObjects( + new ListObjectsRequest(configJSON.bucket) + .withMaxKeys(100) + .withPrefix(configJSON.path + "/" + fileName + '-') + ); + + var sums = $ARRAY(objectListing.getObjectSummaries()); + sums = sums.filter((s) => { + return (!(configJSON.path + "/").equals(s.getKey())); + }).filter((s) => { + return s.getKey().contains('/' + fileName + '-'); + }).sort((a, b) => { + return b.getLastModified().compareTo(a.getLastModified()); + }); + + for (var i = configJSON.limit; i < sums.length; i++) { + var s = sums[i]; + println("Delete object: " + $$.asList(s.getKey(), s.getSize(), s.getLastModified())); + client.deleteObject(configJSON.bucket, s.getKey()); + } + }); + + println('Backup finished, cost: ' + ($$.date().millis() - start) + ' ms.'); + } catch(e) { + println('OSS Error: ' + e); + } finally { + client.shutdown(); + } +}; + +main(); + diff --git a/scripts/osssendfile.js b/scripts/osssendfile.js new file mode 100644 index 0000000..8a293d5 --- /dev/null +++ b/scripts/osssendfile.js @@ -0,0 +1,257 @@ +#! /usr/bin/env runjs + +requireJAR('aliyun-sdk-oss-2.4.1-SNAPSHOT.jar'); +requireJAR('commons-beanutils-1.8.0.jar'); +requireJAR('commons-codec-1.9.jar'); +requireJAR('commons-collections-3.2.1.jar'); +requireJAR('commons-lang-2.5.jar'); +requireJAR('commons-logging-1.2.jar'); +requireJAR('ezmorph-1.0.6.jar'); +requireJAR('hamcrest-core-1.1.jar'); +requireJAR('httpclient-4.4.1.jar'); +requireJAR('httpcore-4.4.1.jar'); +requireJAR('jdom-1.1.jar'); +requireJAR('json-lib-2.4-jdk15.jar'); + +requireJAR('maven:external.jose4j:jose4j:0.5.5'); +requireJAR('maven:org.slf4j:slf4j-api:1.7.21'); + +var oss = require('component-oss.js'); +var args = require('component-args.js'); +var bytes = require('component-bytes.js'); +var counter = require('component-counter.js'); +var gpg = require('component-gpg-ex.js'); + +var File = java.io.File; +var System = java.lang.System; +var FileInputStream = java.io.FileInputStream; +var FileOutputStream = java.io.FileOutputStream; + +var JsonWebKey = Packages.org.jose4j.jwk.JsonWebKey; +var JsonWebEncryption = Packages.org.jose4j.jwe.JsonWebEncryption; +var KeyManagementAlgorithmIdentifiers = Packages.org.jose4j.jwe.KeyManagementAlgorithmIdentifiers; +var ContentEncryptionAlgorithmIdentifiers = Packages.org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers; +var CounterInputStream = Packages.me.hatter.tools.commons.io.CounterInputStream; +var RFile = Packages.me.hatter.tools.commons.io.RFile; +var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil; +var KeyValue = Packages.me.hatter.tools.commons.network.HttpRequest.KeyValue; +var ListObjectsRequest = Packages.com.aliyun.oss.model.ListObjectsRequest; +var AESCryptTool = Packages.me.hatter.tools.commons.security.crypt.AESCryptTool; +var DefaultRollCounter = Packages.me.hatter.tools.commons.io.DefaultRollCounter; + +var main = () => { + var start = $$.date().millis(); + + var parsedArgs = args.parseARGS(['noenc', 'removesourcefile']); + + if ((parsedArgs.args.length != 1) && (parsedArgs.args.length != 3)) { + println('osssendfile.js -- upload file to playsecurity.org'); + println(); + println('osssendfile.js [--config config.json] list'); + println('osssendfile.js [--config config.json] clear'); + println('osssendfile.js [--config config.json] [--noenc] [--removesourcefile] [--jwk \'x\'] file.ext title keywords'); + println('osssendfile.js [--config config.json] [--noenc] [--removesourcefile] [--jwk \'{JWK}\'] file.ext title keywords'); + return; + } + + var configJSON = null; + try { + var config = RFile.from(parsedArgs.values['config'] || '~/.jssp/config/osssendfile.json').string(); + configJSON = JSON.parse(config); + } catch (e) { + println('Parse config error: ' + e); + } + + var hasNoAccessKey = !configJSON.accessKey || !configJSON.secretKey; + var hasNoOidc = !configJSON.oidc; + if (!configJSON || !configJSON.bucket || !configJSON.endpoint || !configJSON.token || (hasNoAccessKey && hasNoOidc)) { + println('----- Config format -----'); + println('{'); + println(' \"endpoint\": \"\",'); + println(' \"accessKey\": \"\",'); + println(' \"secretKey\": \"\",'); + println(' \"bucket\": \"\",'); + println(' \"token\": \"\",'); + println(' \"deleteSourceFile\": false'); + println('}'); + println('----- OR -----'); + println('{'); + println(' \"endpoint\": \"\",'); + println(' \"bucket\": \"\",'); + println(' \"token\": \"\",'); + println(' \"oidc\": {'); + println(' \"sub\": \"\",'); + println(' \"client_id\": \"\",'); + println(' \"client_secret\": \"\"'); + println(' },'); + println(' \"deleteSourceFile\": false'); + println('}'); + return; + } + + var stsCredential = null; + if (configJSON.oidc) { + var params = $$.list(); + params.add(new KeyValue('client_id', configJSON.oidc.clientId)); + params.add(new KeyValue('client_secret', configJSON.oidc.clientSecret)); + params.add(new KeyValue('sub', configJSON.oidc.sub)); + var createStsUrl = 'https://hatter.ink/oidc/create_sts.json'; + var sts = $$.httpRequest().readTimeout(5 * 60 * 1000).url(createStsUrl).post(params); + + var stsJSON = JSON.parse(sts.toString()); + if (stsJSON.status != 200) { + println('Get STS failed: ' + stsJSON.message); + return; + } + stsCredential= stsJSON.data; + } + + var OSSClient = Packages.com.aliyun.oss.OSSClient; + var client; + if (stsCredential) { + client = new OSSClient(configJSON.endpoint, stsCredential.accessKeyId, stsCredential.accessKeySecret, stsCredential.securityToken); + } else { + client = new OSSClient(configJSON.endpoint, configJSON.accessKey, configJSON.secretKey); + } + try { + if (parsedArgs.args.length == 1) { + var getSums = () => { + var objectListing = client.listObjects( + new ListObjectsRequest(configJSON.bucket) + .withMaxKeys(100) + .withPrefix('tempfiles/temp_transfer_') + ); + return $ARRAY(objectListing.getObjectSummaries()); + }; + + var commandMap = { + 'list': () => { + var sums = getSums(); + println('Find ' + sums.length + ' object(s).') + sums.forEach((s) => { + println("Object: " + $$.asList(s.getKey(), s.getSize(), s.getLastModified())); + }); + println('DONE @' + new Date()); + }, + 'clear': () => { + var sums = getSums(); + println('Find ' + sums.length + ' object(s).') + sums.forEach((s) => { + println("Delete object: " + $$.asList(s.getKey(), s.getSize(), s.getLastModified())); + client.deleteObject(configJSON.bucket, s.getKey()); + }); + println('DONE @' + new Date()); + }, + 'null': (cmd) => { + println('[ERROR] Unknown command: ' + cmd); + } + }; + + (commandMap[parsedArgs.args[0]] || commandMap['null'])(parsedArgs.args[0]); + return; + } + + var file = parsedArgs.args[0]; + var title = parsedArgs.args[1]; + var keywords = parsedArgs.args[2]; + + var ext = (file.lastIndexOf('.') > 0) ? file.substring(file.lastIndexOf('.') + 1) : null; + var sendFile = $$.file(file); + if (!(sendFile.exists())) { + println("File not exists: " + sendFile); + return; + } + + if (!client.doesBucketExist(configJSON.bucket)) { + println("Bucket NOT exists: " + configJSON.bucket); + return; + } + + var isSecure = false; + var tempKey = $$.random().nextIoBytes(16); + var pJwk = parsedArgs.values['jwk']; + if (pJwk) { + var pJwkContent = pJwk[0]; + if ((pJwk[0].length == 0) || ($STR(pJwk[0]) == 'x')) { + pJwkContent = gpg.decrypt('~/jwk.json.asc'); + } + var jwk = JsonWebKey.Factory.newJwk(pJwkContent); + var senderJwe = new JsonWebEncryption(); + senderJwe.setPlaintext(title); + senderJwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT); + senderJwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); + senderJwe.setKey(jwk.getKey()); + var encTitle = 'JWE:' + senderJwe.getCompactSerialization(); + println('Encrypt JWE title: ' + title + ' --> ' + encTitle); + title = encTitle; + + isSecure = true; + tempKey = __.bytes.from(jwk.getKey().getEncoded()); + } + + var isDoDefaultEnc = !parsedArgs.flags['noenc']; + var sendFileTemp = sendFile; + if (isDoDefaultEnc) { + sendFileTemp = $$.file(file + '.tmp'); + println('Encryption local file: ' + sendFile + ' --> ' + sendFileTemp + (isSecure ? ' [secure]': ' [normal]')); + AESCryptTool.gcmEncrypt(tempKey.bytes()).counter(new DefaultRollCounter(sendFile.length()).prefix('Encrypting: ')).from(sendFile).to(sendFileTemp); + } + + var newFile = 'tempfiles/temp_transfer_' + $$.date().millis() + (ext ? ('.' + ext) : ''); + println('Uploading object: ' + sendFileTemp + ' --> ' + newFile + ', file size: ' + bytes.showBytes(sendFileTemp.length())); + var databaseDbGpg = new FileInputStream(sendFileTemp); + var counterIS = new CounterInputStream(databaseDbGpg, counter.getCounterBar(sendFileTemp.length())); + client.putObject(configJSON.bucket, newFile, counterIS); + println(); + + // var ossURL = oss.generateSignedURL(configJSON.endpoint, configJSON.accessKey, configJSON.secretKey, configJSON.bucket, newFile, 600 * 1000); + var ossURL = client.generatePresignedUrl(configJSON.bucket, newFile, new java.util.Date(new java.util.Date().getTime() + 600 * 1000)).toString(); + println('Object URL: ' + ossURL); + + println('Sending document ....'); + var params = $$.list(); + params.add(new KeyValue('jsonp', '1')); + params.add(new KeyValue('token', configJSON.token)); + params.add(new KeyValue('url', ossURL)); + params.add(new KeyValue('title', title)); + params.add(new KeyValue('keywords', keywords)); + if (isDoDefaultEnc) { + if (isSecure) { + params.add(new KeyValue('jwe_secure', "true")); + params.add(new KeyValue('real_length', sendFile.length())); + params.add(new KeyValue('real_sha256', __.rfile.from(sendFile).digest(__.digests.sha256()).asHex())); + } else { + params.add(new KeyValue('encryption', tempKey.asBase64())); + } + } + var res = $$.httpRequest().readTimeout(5 * 60 * 1000).url('https://playsecurity.org/doc/addDoc.jsonp').post(params); + println('Add doc result: ' + res); + + var resJSON = JSON.parse(res.toString()); + + if (resJSON.status == 200) { + println("Deleteing object: " + newFile); + client.deleteObject(configJSON.bucket, newFile); + } else { + println("Object is not deleted: " + newFile); + } + + if (isDoDefaultEnc) { + sendFileTemp.delete(); + } + var deleteSourceFile = configJSON.deleteSourceFile || parsedArgs.flags['removesourcefile'] || false; + if (deleteSourceFile) { + println('Delete file: ' + sendFile); + sendFile.delete(); + } + + println('DONE @' + new Date()); + } catch (e) { + println('OSS Error: ' + e); + } finally { + client.shutdown(); + } +}; + +main(); + diff --git a/scripts/ossuploader.js b/scripts/ossuploader.js new file mode 100644 index 0000000..baa732d --- /dev/null +++ b/scripts/ossuploader.js @@ -0,0 +1,60 @@ +#! /usr/bin/env runjs + +var oss = require('component-oss.js'); +var args = require('component-args.js'); +var counter = require('component-counter.js'); + +oss.requireJARs(); + +var main = () => { + var start = $$.date().millis(); + var parsedArgs = args.parseARGS(); + + if ((parsedArgs.args.length < 1) || (!(parsedArgs.values['config']))) { + println('Config file or file is not assigned.'); + println('ossuploader.js --config config.json filename.ext [target_filename.ext]'); + return; + } + + try { + var config = $$.rFile(parsedArgs.values['config']).string(); + configJSON = JSON.parse(config); + } catch (e) { + println('Parse config error: ' + e); + } + + if (!configJSON || !configJSON.bucket || !configJSON.endpoint || !configJSON.accessKey || !configJSON.secretKey) { + println('----- Config format -----'); + println('{'); + println(' \"endpoint\": \"\",'); + println(' \"bucket\": \"\",'); + println(' \"accessKey\": \"\",'); + println(' \"secretKey\": \"\",'); + println('}'); + return; + } + + println('OSS info: ' + configJSON.bucket + '@' + configJSON.endpoint); + + oss.newClient(configJSON.endpoint, configJSON.accessKey, configJSON.secretKey).runWith((client) => { + if (!client.doesBucketExist(configJSON.bucket)) { + println("Bucket NOT exists: " + configJSON.bucket); + return; + } + + var localFile = parsedArgs.args[0]; + var remoteFile = parsedArgs.args[1] || parsedArgs.args[0].replace(/[^a-zA-Z0-9\.\-]/, '_'); + + println('Uploading file: ' + localFile + ' -> ' + remoteFile); + + var counterIS = oss.createCounterIS(localFile); + client.putObject(configJSON.bucket, remoteFile, counterIS); + println(); + counterIS.close(); + + println('Upload file finished, cost: ' + ($$.date().millis() - start) + ' ms.'); + }); +}; + +main(); + diff --git a/scripts/pivlogin.js b/scripts/pivlogin.js new file mode 100644 index 0000000..10ea609 --- /dev/null +++ b/scripts/pivlogin.js @@ -0,0 +1,19 @@ +#! /usr/bin/env runjs + +function generateLoginUrl() { + var exp = (new Date().getTime() + 1000*10) + ''; + var digest_hex = __.digests.sha256().digest(__.bytes.from(exp).bytes()).asHex(); + var result = $$.shell().commands('card-cli', 'piv-ecsign', '-s', 'r1', '-x', digest_hex, '--json').start(); + var out = result[0].string(); + var outJson = JSON.parse(out); + var signatureBase64 = outJson.signed_data_base64; + return 'https://hatter.ink/login/direct_sign_login.jssp?__auth_before=' + exp + '&__auth_keys=&__auth_sign=' + encodeURIComponent(signatureBase64); +} + +function main() { + var url = generateLoginUrl(); + println('Open URL: ' + url); + $$.shell().commands('open', url).start(); +} + +main(); diff --git a/scripts/proguard.js b/scripts/proguard.js new file mode 100644 index 0000000..d104ba2 --- /dev/null +++ b/scripts/proguard.js @@ -0,0 +1,31 @@ +#! /usr/bin/env runjs + +var osjs = require('component-os.js'); +var packagejs = require('component-package.js'); +var javahomejs = require('component-javahome.js'); +var filesystemjs = require('component-filesystem.js'); + +var PROGUARD_PACKAGE_INFO = { + 'package': 'https://playsecurity.org/getdoc/2442_C0AD8AB45B3FE6BFE30547EDDCE45B85/proguard6.0.3.zip', + 'sha256': '0689f6e10e1308129cea9303981efc185009311cedcbf38fe0df0cd0128fc610', + 'basePath': '~/.jssp/builder/proguard6.0.3', + 'subPath': 'proguard6.0.3', + 'bin': 'bin/proguard.sh' +}; + +var main = () => { + xprintln('[INFO] Get proguard local package info.'); + var proguardLocalPackage = packagejs.getLocalPackage(PROGUARD_PACKAGE_INFO, true); + + var commandArgs = []; + var buildCommands = []; + buildCommands.push(proguardLocalPackage.binFile); + $ARR($ARGS).forEach((a) => { buildCommands.push(a); commandArgs.push(a); }); + + xprintln('[INFO] PROGUARD_HOME = ' + proguardLocalPackage.packageHome); + xprintln('[INFO] ARGUMENTS = ' + $ARR(commandArgs).toJavaList()); + + $$.shell(true).commands(buildCommands).run(); +}; + +main(); diff --git a/scripts/rename.js b/scripts/rename.js new file mode 100644 index 0000000..8fa8f33 --- /dev/null +++ b/scripts/rename.js @@ -0,0 +1,27 @@ +#! /usr/bin/env runjs + +var main = function() { + var files = __.rfile.from('.').file().listFiles(); + for (var i = 0; i < files.length; i++) { + var f = files[i]; + if (!f.name.endsWith('.mp4')) { + continue; + } + var lastDotIndex = f.name.lastIndexOf('.'); + if (lastDotIndex < 0) { + continue; + } + var filename = f.name.substring(0, lastDotIndex); + var isAllHex = /^[0-9A-Fa-f]+$/.test(filename); + var newFilename; + if (isAllHex) { + newFilename = __.bytes.fromHex(filename).toString() + '.mp4'; + } else { + newFilename = __.bytes.from(filename).asHex() + '.mp4'; + } + xprintln('[INFO] File: ' + filename, '->', newFilename); + f.renameTo(__.rfile.from('./' + newFilename).file()); + } +}; + +main(); diff --git a/scripts/runjshelp.js b/scripts/runjshelp.js new file mode 100644 index 0000000..b407900 --- /dev/null +++ b/scripts/runjshelp.js @@ -0,0 +1,161 @@ +#! /usr/bin/env runjs +var System = java.lang.System; +var JarFile = java.util.jar.JarFile; +var StringUtil = Packages.me.hatter.tools.commons.string.StringUtil; +var StandaloneMainInteractive = Packages.me.hatter.tools.jssp.main.StandaloneMainInteractive; +var ConsoleReadTool = Packages.me.hatter.tools.commons.console.ConsoleReadTool; +var ClassLoaderUtil = Packages.me.hatter.tools.commons.classloader.ClassLoaderUtil; +var ReflectUtil = Packages.me.hatter.tools.commons.reflect.ReflectUtil; + +var searchClasses = (systemClassLoader) => { + var classes = []; + $ARRAY(systemClassLoader.getURLs()).forEach((u) => { + var jarFile = new JarFile(u.getFile()); + var jarEntryEnum = jarFile.entries(); + while (jarEntryEnum.hasMoreElements()) { + var jarFileEntry = jarEntryEnum.nextElement(); + var jarFileEntryName = jarFileEntry.getName(); + if (jarFileEntryName.endsWith('.class')) { + classes.push(jarFileEntryName); + } + } + }); + return classes; +}; + +var convertFileNameToClasName = (c) => { + if (c.endsWith('.class')) { + c = c.substring(0, c.length - 6); + } + if (c.contains('/')) { + c = c.replace(/\//g, '.'); + } + return c; +}; + +var getShortClassName = (c) => { + var lastDot = c.lastIndexOf('.'); + return c.substring(lastDot + 1); +}; + +var isMatchCommandFilter = (c, fullCommandLines) => { + if (fullCommandLines.length > 1) { + for (var i = 1; i < fullCommandLines.length; i++) { + var filterCmd = fullCommandLines[i]; + var isMatchShortClassName = filterCmd.startsWith('S'); + filterCmd = filterCmd.substring(1); + var matchClassName = isMatchShortClassName? getShortClassName(convertFileNameToClasName(c)): c; + if (!matchClassName.toLowerCase().contains(filterCmd.toLowerCase())) { + return false; + } + } + } + return true; +}; + +var main = () => { + StandaloneMainInteractive.initJLine(); + var systemClassLoader = ClassLoaderUtil.getSystemClassLoader(); + + ConsoleReadTool.from('usage> ').loop((ln) => { + var fullCommandLine = $STR(ln); + var fullCommandLines = fullCommandLine.split(/\s+/); + var cmd = fullCommandLines[0]; + if ($$.asList('ls', 'll', 'list').contains(cmd)) { + $ARRAY(systemClassLoader.getURLs()).forEach((u) => { + println(u); + }); + } else if ($$.asList('exit', 'quit').contains(cmd)) { + println('+ Bye!'); + System.exit(0); + } else if ($$.asList('desc', 'describe').contains(cmd)) { + if (fullCommandLines.length == 1) { + println('Cmd format error.') + } else { + var c = convertFileNameToClasName(fullCommandLines[1]); + try { + var cls = $$.clazz(c); + var fields = $ARRAY(ReflectUtil.getDeclaredFields(cls)); + if (fields && (fields.length > 0)) { + println('Field(s):'); + fields.forEach((f) => { + println(' ' + f); + }); + } + var methods = $ARRAY(ReflectUtil.getDeclaredMethods(cls)); + if (methods && (methods.length > 0)) { + println('Method(s):'); + methods.forEach((m) => { + println(' ' + m); + }); + } + } catch (e) { + println('Error in desc : ' + c); + } + } + } else if ($$.asList('search').contains(cmd)) { + searchClasses(systemClassLoader).forEach((c) => { + if (!isMatchCommandFilter(c, fullCommandLines)) { + return; + } + println(c); + }); + } else if ($$.asList('import').contains(cmd)) { + searchClasses(systemClassLoader).forEach((c) => { + if (!isMatchCommandFilter(c, fullCommandLines)) { + return; + } + var className = convertFileNameToClasName(c); + var showClassName = getShortClassName(className); + println('var ' + showClassName + ' = ' + (className.startsWith('java.')? '': 'Packages.') + className + ';'); + }); + } else if ($$.asList('require').contains(cmd)) { + if (fullCommandLines.length == 1) { + println('Cmd format error.'); + } else { + for (var i = 1; i < fullCommandLines.length; i++) { + requireJAR(fullCommandLines[i]); + } + } + } else if ($$.asList('tree').contains(cmd)) { + var classMap = $$.treeMap(); + searchClasses(systemClassLoader).forEach((c) => { + if (!isMatchCommandFilter(c, fullCommandLines)) { + return; + } + var className = c.substring(0, c.length - 6); + var classNames = className.split('\/'); + var baseMap = classMap; + $ARRAY(classNames).forEach((p) => { + var m = baseMap.get(p); + if (m == null) { + m = $$.treeMap(); + baseMap.put(p, m); + } + baseMap = m; + }); + }); + var depth = 0; + var printMap = (m) => { + $ARRAY(m.keySet()).forEach((p) => { + var m2 = m.get(p); + var hasSub = (m2 != null) && (!m2.isEmpty()); + println(StringUtil.repeat(' ', depth) + p + (hasSub? '.': '')); + if (hasSub) { + depth += p.length + 1; + printMap(m2); + depth -= p.length + 1; + } + }); + }; + println(classMap.size()); + printMap(classMap); + } else { + if (cmd != '') { + println('Unknow command: ' + cmd); + } + } + }); +}; + +main(); diff --git a/scripts/scancert.js b/scripts/scancert.js new file mode 100644 index 0000000..b955cdf --- /dev/null +++ b/scripts/scancert.js @@ -0,0 +1,116 @@ +#! /usr/bin/env runjs + +var TimeUnit = java.util.concurrent.TimeUnit; +var DirWalkTool = Packages.me.hatter.tools.commons.file.DirWalkTool; +var DirWalker = Packages.me.hatter.tools.commons.file.DirWalkTool.DirWalker; +var X509CertUtil = Packages.me.hatter.tools.commons.security.cert.X509CertUtil; + +var OKGREEN = '\033[92m'; +var WARNING = '\033[93m'; +var FAIL = '\033[91m'; +var UNDERLINE = '\033[4m'; +var ENDC = '\033[0m'; + +var main = () => { + if ($ARGS == null || $ARGS.length == 0) { + println('scancert.js - Scan cert.') + println(); + println('ERROR: NO arguments assigned!'); + println('scancert.js '); + return; + } + var scanCount = 0; + var warnings = []; + var fails = []; + var minDayLeft = null; + var maxDayLeft = null; + var scanFile = (is, file) => { + var bytes = $$.io().bytesAndClose(is); + if (bytes.toString().contains('BEGIN CERTIFICATE')) { + scanCount++; + println('[INFO] Cert pem file found: ' + file); + // is cert pem file + var certs = X509CertUtil.orderX509CertificateList(X509CertUtil.parseX509CertificateList(bytes.getBytes())); + if (certs.size() < 1) { + println('[ERROR] Cannot find any cert.'); + } else { + var todayMillis = $$.date().millis(); + var leafCert = certs.get(0); + var notAfter = leafCert.getNotAfter(); + var altNames = leafCert.getSubjectAlternativeNames(); + + var colorStart = OKGREEN; + var colorEnd = ENDC; + if (notAfter.getTime() < (todayMillis + TimeUnit.DAYS.toMillis(10))) { + colorStart = FAIL; + fails.push(file); + } else if (notAfter.getTime() < (todayMillis + TimeUnit.DAYS.toMillis(30))) { + colorStart = WARNING; + warnings.push(file); + } + var dayLeft = parseInt((notAfter.getTime() - todayMillis) / TimeUnit.DAYS.toMillis(1)); + minDayLeft = (minDayLeft == null)? dayLeft: Math.min(minDayLeft, dayLeft); + maxDayLeft = (maxDayLeft == null)? dayLeft: Math.max(maxDayLeft, dayLeft); + println(colorStart + + 'Expires: '+ $$.date().fmt('yyyy-MM-dd').format(notAfter) + + ' (' + dayLeft + ' days)' + + colorEnd + + ', DNS Name(s): ' + $ARRAY(altNames).map((n) => { return n.get(1) }).join(', ')); + } + } + }; + + var f = $$.file($ARGS[0]); + if (!f.exists()) { + println('File or Directory not exists: ' + f); + return; + } + if (f.isFile()) { + scanFile($$.rFile(f).rStream().stream(), f); + } else { + var dir = f; + println('[INFO] Scan .pem file(s): ' + dir); + var walkTool = new DirWalkTool(dir); + + walkTool.walk(new DirWalker({ + "accept": (file) => { + if (file.isDirectory()) { + return true; + } + if (file.getName().endsWith('.pem')) { + return true; + } + }, + "readInputStream": (is, file) => { + scanFile(is, file); + } + })); + } + println(); + println('Scaned file: ' + scanCount); + if (warnings.length > 0) { + print(WARNING); + println('WARNINGS:'); + warnings.forEach((f) => { + println(f); + }); + print(ENDC); + } + if (fails.length > 0) { + print(FAIL); + println('FAILS:'); + fails.forEach((f) => { + println(f); + }); + print(ENDC); + } + if ((warnings.length == 0) && (fails.length == 0)) { + println(OKGREEN + 'No waning or fail found.' + ENDC) + } + if ((minDayLeft != null) && (maxDayLeft != null)) { + println('Day left, min: ' + minDayLeft + ', max: ' + maxDayLeft); + } +}; + +main(); + diff --git a/scripts/secureosssendfile.js b/scripts/secureosssendfile.js new file mode 100644 index 0000000..43766d5 --- /dev/null +++ b/scripts/secureosssendfile.js @@ -0,0 +1,59 @@ +#! /usr/bin/env runjs + +var jose = require('component-jose.js'); +var args = require('component-args.js'); + +var main = () => { + var parsedArgs = args.parseARGS(); + + var secureosssendfileConfRFile = __.rfile.from('~/.jssp/config/secureosssendfile.jwk'); + if (secureosssendfileConfRFile.notExists()) { + xprintln('[ERROR] secureosssendfile.jwk NOT found.'); + return; + } + var jwk = jose.jwk.load(secureosssendfileConfRFile.string()); + + var osssendfilejsRFile = __.rfile.from('~/bin/osssendfile.js'); + if (osssendfilejsRFile.notExists()) { + xprintln('[ERROR] osssendfile.js NOT found.') + return; + } + + if ((parsedArgs.args.length != 2) && (parsedArgs.args.length != 3)) { + println('secureosssendfile.js -- secure upload file to playsecurity.org'); + println(); + println('secureosssendfile.js file.ext [newFn] keywords'); + return; + } + var fn = parsedArgs.args[0]; + var newFn = fn; + var kw; + if (parsedArgs.args.length == 2) { + kw = parsedArgs.args[1]; + } else { + newFn = parsedArgs.args[1]; + kw = parsedArgs.args[2]; + } + + if ($STR(newFn) == '_IN') { + print('Input new fn: '); + newFn = java.lang.System.console().readLine(); + println('[INFO] Input file name: ' + newFn); + } + + + var encFn = $$.date().millis() + '.gpg'; + xprintln('[INFO] GPG encrypt file: ' + fn + " -> " + encFn) + $$.shell(true).commands('gpg', '-e', '-r', 'D0386B7F', '-o', encFn, fn).run(); + + var jweNewFn = 'JWE:' + jose.jwe.enc(jwk, newFn); + + xprintln('[INFO] Send file: ' + encFn + ' -> ' + jweNewFn); + $$.shell(true).commands('osssendfile.js', encFn, jweNewFn, kw).run(); + + $$.file(encFn).delete(); + xprintln('[INFO] Done!') +}; + +main(); + diff --git a/scripts/server.js b/scripts/server.js new file mode 100644 index 0000000..ad00e24 --- /dev/null +++ b/scripts/server.js @@ -0,0 +1,114 @@ +#! /usr/bin/env runjs + +requireJS('component-httpserver.js'); + +var FileInputStream = java.io.FileInputStream; +var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil; + +var getContentTypeByExt = (ext) => { + if (ext == null) { return 'application/octet-stream' } + var lowerExt = ext.toLowerCase(); + + if ($$.asList('jpg', 'jpe', 'jpeg').contains(lowerExt)) { + return 'image/jpeg'; + } else if ($$.asList('png').contains(lowerExt)) { + return 'image/png'; + } else if ($$.asList('txt', 'text', 'pem').contains(lowerExt)) { + return 'text/plain'; + } else if ($$.asList('htm', 'html').contains(lowerExt)) { + return 'text/html'; + } else if ($$.asList('js').contains(lowerExt)) { + return 'text/javascript'; + } else if ($$.asList('json').contains(lowerExt)) { + return 'application/json'; + } else if ($$.asList('doc').contains(lowerExt)) { + return 'application/msword'; + } else if ($$.asList('xls').contains(lowerExt)) { + return 'application/vnd.ms-excel'; + } else if ($$.asList('ppt').contains(lowerExt)) { + return 'application/vnd.ms-powerpoint'; + } else if ($$.asList('pdf').contains(lowerExt)) { + return 'application/pdf'; + } else if ($$.asList('crt').contains(lowerExt)) { + return 'application/x-x509-ca-cert'; + } else if ($$.asList('mp3').contains(lowerExt)) { + return 'audio/mp3'; + } else if ($$.asList('mp4').contains(lowerExt)) { + return 'video/mpeg4'; + } else if ($$.asList('xml').contains(lowerExt)) { + return 'text/xml'; + } + + // Unknow ext. + return 'application/octet-stream'; +}; + +var main = () => { + if (($ARGS == null) || ($ARGS.length < 2)) { + println('server.js - Run server.'); + println(); + println('ERROR: NO arguments assigned!') + println('CMD: server.js ') + println(' port server port') + println(' path server path') + return; + } + var port = parseInt($ARGS[0]); + var path = $STR($ARGS[1]); + if (isNaN(port) || (port <= 0) || (port > 65535)) { + println('ERROR: port error: ' + port) + return; + } + var filePath = $$.file(path); + if (!filePath.exists() || !filePath.isDirectory()) { + println('ERROR: path not exists or not a directory: ' + path) + return; + } + + serveHTTP(port, (httpExchange) => { + var requestURI = httpExchange.getRequestURI().toString(); + println('Request received: ' + requestURI); + + try { + var requestPath = requestURI.startsWith('/')? requestURI.substring(1): requestURI; + var f = $$.file(filePath, requestPath); + if (!f.exists()) { + return { "status": 404, "text": "404\n\nResource not found: " + requestURI + '\n' }; + } + + if (f.isDirectory()) { + if (!requestURI.endsWith('/')) { + return { "status": 302, "headers": [["Location", requestURI + '/' ]], "bytes": $$.byteArray(0) }; + } + var result = []; + $ARRAY(f.list()).forEach((fn) => { + result.push(fn); + }); + return {"text": "Directory listing:\n\n" + result.join('\n') + '\n' }; + } + + var fileExtIndex = f.getName().lastIndexOf('.'); + var fileExt = (fileExtIndex > 0)? f.getName().substring(fileExtIndex + 1): null; + + var fileLength = f.length(); + httpExchange.sendResponseHeaders(200, 0); + var responseHeaders = httpExchange.getResponseHeaders(); + responseHeaders.set('Content-Type', getContentTypeByExt(fileExt)); + responseHeaders.set('Content-Length', fileLength); + var response = httpExchange.getResponseBody(); + var fis = new FileInputStream(f); + IOUtil.copy(fis, response) + IOUtil.closeQuietly(fis); + IOUtil.closeQuietly(response); + } catch(e) { + if (e && e.printStackTrace) { + e.printStackTrace(); + } else { + println('[ERROR] Exception: ' + e); + } + return { "status": "500", "text": "[ERROR] Exception: " + e + '\n' }; + } + }); +}; + +main(); diff --git a/scripts/server2.js b/scripts/server2.js new file mode 100644 index 0000000..9b70119 --- /dev/null +++ b/scripts/server2.js @@ -0,0 +1,35 @@ +#! /usr/bin/env runjs + +var httpserver = require('component-httpserver-ex.js'); + +var main = () => { + if (($ARGS == null) || ($ARGS.length < 2)) { + println('server2.js - Run server2.'); + println(); + println('ERROR: NO arguments assigned!'); + println('CMD: server2.js '); + println(' port server port'); + println(' path server path'); + return; + } + var port = parseInt($ARGS[0]); + var path = $STR($ARGS[1]); + if (isNaN(port) || (port <= 0) || (port > 65535)) { + println('ERROR: port error: ' + port); + return; + } + var filePath = $$.file(path); + if (!filePath.exists() || !filePath.isDirectory()) { + println('ERROR: path not exists or not a directory: ' + path); + return; + } + + httpserver.serveHTTP(port, (httpExchange) => { + return httpserver.handleFile(httpExchange, { handleDir: true, basePath: path }) || { + status: 404, + text: 'File not found!' + }; + }); +}; + +main(); diff --git a/scripts/showmyip.js b/scripts/showmyip.js new file mode 100644 index 0000000..e6d2e23 --- /dev/null +++ b/scripts/showmyip.js @@ -0,0 +1,11 @@ +#! /usr/bin/env runjs + +var main = () => { + var myIP = $$.httpRequest() + .url('http://ifconfig.io/') + .addHeader('User-Agent', 'curl/0.0.0') + .get().toString().trim(); + println('IP address is: ' + myIP); +}; + +main(); diff --git a/scripts/signpdf.js b/scripts/signpdf.js new file mode 100644 index 0000000..c63530f --- /dev/null +++ b/scripts/signpdf.js @@ -0,0 +1,140 @@ +#! /usr/bin/env runjs + +requireJAR('bcpkix-jdk15on-154.jar'); +requireJAR('bcprov-jdk15on-154.jar'); +requireJAR('bcprov-ext-jdk15on-154.jar'); +requireJAR('itextpdf-5.5.11.jar'); + +var JavaArray = java.lang.reflect.Array; +var Security = java.security.Security; +var StringReader = java.io.StringReader; +var BufferedReader = java.io.BufferedReader; +var FileOutputStream = java.io.FileOutputStream; +var X509Certificate = java.security.cert.X509Certificate; +var Rectangle = Packages.com.itextpdf.text.Rectangle; +var PdfName = Packages.com.itextpdf.text.pdf.PdfName; +var PdfReader = Packages.com.itextpdf.text.pdf.PdfReader; +var PdfStamper = Packages.com.itextpdf.text.pdf.PdfStamper; +var PdfPKCS7 = Packages.com.itextpdf.text.pdf.security.PdfPKCS7; +var MakeSignature = Packages.com.itextpdf.text.pdf.security.MakeSignature; +var DigestAlgorithms = Packages.com.itextpdf.text.pdf.security.DigestAlgorithms; +var BouncyCastleDigest = Packages.com.itextpdf.text.pdf.security.BouncyCastleDigest; +var PrivateKeySignature = Packages.com.itextpdf.text.pdf.security.PrivateKeySignature; +var CryptoStandard = Packages.com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard; +var ExternalSignatureContainer = Packages.com.itextpdf.text.pdf.security.ExternalSignatureContainer; +var ExternalBlankSignatureContainer = Packages.com.itextpdf.text.pdf.security.ExternalBlankSignatureContainer; +var BouncyCastleProvider = Packages.org.bouncycastle.jce.provider.BouncyCastleProvider; +var PrivateKeyParseTool = Packages.me.hatter.tools.commons.security.rsa.PrivateKeyParseTool; +var X509CertUtil = Packages.me.hatter.tools.commons.security.cert.X509CertUtil; + +var emptySignature = (src, dest, fieldname, chain, reason, location) => { + var reader = new PdfReader(src); + var os = new FileOutputStream(dest); + var stamper = PdfStamper.createSignature(reader, os, '\0'); + var appearance = stamper.getSignatureAppearance(); + appearance.setVisibleSignature(new Rectangle(20, 748, 180, 780), 1, fieldname); + appearance.setCertificate(chain[0]); + if (reason) { + appearance.setReason(reason); + } + if (location) { + appearance.setLocation(location); + } + var external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED); + MakeSignature.signExternalContainer(appearance, external, 8192); +}; + +var createSignature = (src, dest, fieldname, pk, chain) => { + var reader = new PdfReader(src); + var os = new FileOutputStream(dest); + var external = new ExternalSignatureContainer({ + 'sign': (is) => { + var signature = new PrivateKeySignature(pk, "SHA256", "BC"); + var hashAlgorithm = signature.getHashAlgorithm(); + var digest = new BouncyCastleDigest(); + var sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false); + var hash = DigestAlgorithms.digest(is, digest.getMessageDigest(hashAlgorithm)); + var sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS); + var extSignature = signature.sign(sh); + sgn.setExternalDigest(extSignature, null, signature.getEncryptionAlgorithm()); + return sgn.getEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS); + }, + 'modifySigningDictionary': (signDic) => { + // DO NOTHING + } + }); + MakeSignature.signDeferred(reader, fieldname, os, external); +}; + +var printConfigFileFormat = () => { + println('Format:'); + println('{'); + println(' "certs": "/certs.pem",'); + println(' "privKey": "/privKey.pem.gpg"'); + println('}'); +}; + +var main = () => { + if ($ARGS == null || $ARGS.length == 0) { + println('signpdf.js - Sign PDF.') + println(); + println('ERROR: NO arguments assigned!'); + println('signpdf.js [reason [location]]'); + return; + } + var reason = ($ARGS.length > 1)? $ARGS[1]: null; + var location = ($ARGS.length > 2)? $ARGS[2]: null; + var pdf = $$.file($ARGS[0]); + if (!pdf.exists()) { + println('File not exists: ' + pdf); + return; + } + if (!pdf.getName().toLowerCase().endsWith('.pdf')) { + println('File is not PDF: ' + pdf); + return; + } + var configFile = $$.file($$.prop('user.home'), '.signpdf.js.json'); + if (!configFile.exists()) { + println('SignPDF.js config file not found: ' + configFile); + printConfigFileFormat(); + return; + } + var configObject = JSON.parse($$.rFile(configFile).rReader().stringAndClose()); + if (!configObject.privKey || !configObject.certs) { + println('Config file error: ' + configFile); + printConfigFileFormat(); + return; + } + if ($$.file($ARGS[0].replace('.pdf', '-signed.pdf')).exists()) { + println('Target file exists: ' + $ARGS[0].replace('.pdf', '-signed.pdf')); + return; + } + Security.addProvider(new BouncyCastleProvider()); + + var result = $$.shell().commands('sh', '-c', 'cat ' + configObject.privKey + ' | gpg').start(); + var out = result[0].rStream().rReader().stringAndClose(); + var err = result[1].rStream().rReader().stringAndClose(); + if (err.contains('public key decryption failed')) { + println('+ Decrypt file FAILED: ' + configObject.privKey); + if (!Packages.me.hatter.tools.jssp.main.StandaloneMain.JSSP_MAIN_MUTE) { + println("ERROR detail:\n" + err); + } + return; + } + + var privateKeyParseTool = new PrivateKeyParseTool(new BufferedReader(new StringReader(out))); + var certList = X509CertUtil.parseX509CertificateList($$.rFile(configObject.certs).rStream().bytesAndClose()); + + var chain = certList.toArray(JavaArray.newInstance(certList.get(0).getClass(), certList.size())); + var pk = privateKeyParseTool.read(); + var temp = '~' + $$.date().millis() + '.pdf'; + try { + emptySignature(pdf, temp, "sig", chain, reason, location); + createSignature(temp, $ARGS[0].replace('.pdf', '-signed.pdf'), "sig", pk, chain); + } finally { + $$.file(temp).delete(); + } +}; + +main(); + diff --git a/scripts/split.js b/scripts/split.js new file mode 100644 index 0000000..3c75f79 --- /dev/null +++ b/scripts/split.js @@ -0,0 +1,95 @@ +#! /usr/bin/env runjs + +var argsjs = require('component-args.js'); + +var parseSize = (s) => { + if (s == null) { return $$.num(0); } + s = s.toLowerCase(); + if (!(/^\d+[kmg]?$/i.test(s))) { + throw 'Size format error: ' + s; + } + if (s.endsWith('k')) { + return $$.num(s.substring(0, s.length - 1)).mul(1024); + } + if (s.endsWith('m')) { + return $$.num(s.substring(0, s.length - 1)).mul(1024).mul(1024); + } + if (s.endsWith('g')) { + return $$.num(s.substring(0, s.length - 1)).mul(1024).mul(1024).mul(1024); + } + return $$.num(s); +}; + +var main = () => { + var args = argsjs.parseDefARGs(['h', 'help']); + if ((args.flg('h', 'help')) || (args.length == 0)) { + println('split.js '); + println(' -h, --help Print help'); + println(' -s, --size File size(default 20m)'); + println(' -p, --prefix File prefix(default filename + ".")'); + println(' --suffix File suffix(default "")'); + return; + } + var file = $$.file(args[0]); + if (!file.exists()) { + xprintln('[ERROR] File not exists: ' + file); + return; + } + var size = parseSize(args.val('s', 'size') || '20m'); + xprintln('[INFO] Split size: ' + size); + + if (size.compareTo(0) < 0) { + xprintln('[ERROR] Split file size cannot less than 0: ' + size); + return; + } + if (size.compareTo(file.length()) >= 0) { + xprintln('[ERROR] Split file size larger or equals then origin file, ' + size + ' vs ' + file.length()); + return; + } + + var prefix = args.val('p', 'prefix') || file.getName(); + if (!prefix.endsWith('.')) { prefix += '.'; } + xprintln('[INFO] Split file prefix: ' + prefix); + var suffix = args.val('suffix') || ''; + if (!suffix.startsWith('.') && ($STR(suffix) != '')) { suffix = '.' + suffix; } + xprintln('[INFO] Split file suffix: ' + (($STR(suffix) == '') ? '(empty)' : suffix)); + + var fileIndex = 0; + var writted = $$.num(0); + var buff = $$.byteArray(1024); + + var fnList = []; + var fn = prefix + $$.numFormat('000').format(fileIndex) + suffix; + if ($$.file(fn).exists()) { + xprintln('[ERROR] File exists: ' + fn); + return; + } + + fnList.push(fn); + xprintln('[INFO] Write file: ' + fn); + var os = new java.io.BufferedOutputStream(new java.io.FileOutputStream($$.file(fn))); + var is = $$.rFile(file).rStream().buffered().stream(); + for (var len; ((len = is.read(buff)) != -1);) { + os.write(buff, 0, len); + writted = writted.add(len); + if (writted.compareTo(size.mul(fileIndex + 1)) >= 0) { + os.close(); + fileIndex++; + if (writted.compareTo(file.length()) < 0) { + fn = prefix + $$.numFormat('000').format(fileIndex) + suffix; + fnList.push(fn); + xprintln('[INFO] Write file: ' + fn); + os = new java.io.BufferedOutputStream(new java.io.FileOutputStream($$.file(fn))); + } else { + os = null; + } + } + } + if (os != null) { os.close(); } + println(); + xprintln('[OK] Use command to join file:\ncat ' + fnList.join(' \\\n ') + ' \\\n > ' + file.getName()); + println(); + xprintln('[INFO] Split file done!'); +}; + +main(); diff --git a/scripts/sshkeygen.js b/scripts/sshkeygen.js new file mode 100644 index 0000000..fec25db --- /dev/null +++ b/scripts/sshkeygen.js @@ -0,0 +1,31 @@ +#! /usr/bin/env runjs + +var KeyPairGenerator = java.security.KeyPairGenerator; +var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes; +var UnixArgsUtil = Packages.me.hatter.tools.commons.args.UnixArgsUtil; +var SSHKeyGen = Packages.me.hatter.tools.commons.security.ssh.SSHKeyGen; + +var main = () => { + UnixArgsUtil.parseGlobalArgs($ARGS); + var args = UnixArgsUtil.ARGS.args(); + if (UnixArgsUtil.ARGS.flags().containsAny('h', 'help')) { + println('sshkeygen.js - Generate SSH keypair.') + println(); + println('sshkeygen.js [--h[elp]] [-keyLength 4096] [-serverName server_name]'); + return; + } + + var kpg = KeyPairGenerator.getInstance("RSA"); + var keyLen = $$.asInt(UnixArgsUtil.ARGS.kvalue('keyLength') || '2048'); + if (keyLen < 1024) { + println('Key length is less than 1024 bit: ' + keyLen); + return; + } + kpg.initialize(keyLen); + var kp = kpg.generateKeyPair(); + + println(SSHKeyGen.encodePublicKey(kp.getPublic(), UnixArgsUtil.ARGS.kvalue('serverName') || 'test@example.com')); + println(Bytes.from(kp.getPrivate().getEncoded()).asPem('PRIVATE KEY')); +}; + +main(); \ No newline at end of file diff --git a/scripts/sync.js b/scripts/sync.js new file mode 100644 index 0000000..2f0e44d --- /dev/null +++ b/scripts/sync.js @@ -0,0 +1,53 @@ +#! /usr/bin/env runjs + +var main = () => { + if ($ARGS && ($ARGS.length > 0)) { + var userHome = $$.prop('user.home'); + if ($STR($ARGS[0]) == 'md') { + if (__.stringutil.isEmpty($$.shell().commands('which', 'markdowndocs.js').start()[0])) { + xprintln('[ERROR] Command markdowndocs.js not found.'); + return; + } + $$.shell().inheritIO().commands('markdowndocs.js').run(); + } + if ($STR($ARGS[0]) == 'ms') { + if (__.stringutil.isEmpty($$.shell().commands('which', 'markdownslide.js').start()[0])) { + xprintln('[ERROR] Command markdownslide.js not found.'); + return; + } + $$.shell().inheritIO().commands('markdownslide.js').run(); + } + } + + println('[INFO] 1. Git Add All'); + $$.shell().inheritIO().commands('git', 'add', '.').run(); + println('[INFO] 2. Git Commit All'); + $$.shell().inheritIO().commands('git', 'commit', '-a', '-m', "'auto sync'").run(); + println('[INFO] 3. Git Push'); + var gitPushError = false; + $$.shell().commands('git', 'push').run((out, err) => { + if (err && (err.string().contains('Connection closed by remote host')) || err.string().contains('make sure you have the correct access rights')) { + xprintln('[ERROR] Git Push FAILED!'); + gitPushError = true; + } + }); + if (gitPushError) { return; } + println('[INFO] 4. Sync Server Repo'); + var path = $$.file('.').getAbsolutePath(); + var indexOfPage = path.indexOf('/page'); + if (indexOfPage > 0) { + path = path.substring(0, indexOfPage); + } else { + path = path.substring(0, path.length - 2); + } + path = path.substring(path.lastIndexOf('/') + 1); + var updatePageUrl = 'https://playsecurity.org/update_pages?' + path; + try { + println($$.httpRequest().connTimeout(600).readTimeout(10000).url(updatePageUrl).get()); + } catch (e) { + xprintln('[WARN] Update pages failed, try cURL mode.'); + $$.shell().inheritIO().ignoreError(true).commands('curl', updatePageUrl).run(); + } +}; + +main(); diff --git a/scripts/tinyca.js b/scripts/tinyca.js new file mode 100644 index 0000000..c323e4d --- /dev/null +++ b/scripts/tinyca.js @@ -0,0 +1,478 @@ +#! /usr/bin/env runjs + +requireJS('component-json.js'); +requireJS('component-colorprint.js'); +requireJS('component-gpg.js'); + +requireJAR('bcpkix-jdk15on-154.jar'); +requireJAR('bcprov-ext-jdk15on-154.jar'); +requireJAR('bcprov-jdk15on-154.jar'); +requireJAR('crypto-1.0.jar'); + +var StringReader = java.io.StringReader; +var BufferedReader = java.io.BufferedReader; +var TimeUnit = java.util.concurrent.TimeUnit; +var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes; +var PEMUtil = Packages.me.hatter.tools.commons.security.pem.PEMUtil; +var UnixArgsUtil = Packages.me.hatter.tools.commons.args.UnixArgsUtil; +var X509CertUtil = Packages.me.hatter.tools.commons.security.cert.X509CertUtil; +var PrivateKeyParseTool = Packages.me.hatter.tools.commons.security.rsa.PrivateKeyParseTool; +var KeyPairGenerateTool = Packages.me.hatter.tools.commons.security.key.KeyPairGenerateTool; +var CertificateAuthority = Packages.me.hatter.tools.crypto.ca.CertificateAuthority; + + +var printHelp = () => { + println('tinyca.js - Tiny CA.') + println(); + println('tinyca.js '); + println('type - _, global, ca, intermediate, server, client'); + println('command, cases below:'); + println(' type = _, global - init'); + println(' type = ca - create, list, delete'); + println(' type = intermediate - create, list, delete'); + println(' type = server - create, list, delete'); + println(' type = client - create, list, delete'); + println('params:'); + println(' -type - RSA or EC'); + println(' -keyLength - Key length'); + println(' -validYear - Valid year(s)'); + println(' -certId - Cert ID'); + println(' -subject - Subject'); + println(' -dnsName - DNS name(s)'); +}; + +var dvalue = (key) => { + var ks = key.split(/\./g); + var val = $GLOBAL(); + for (var i = 0; i < ks.length; i++) { + var val2 = val[ks[i]]; + if (val2 == null) { return null; } + val = val2; + } + return val; +}; + +var getTypeKeyLengthKeyPair = (ty) => { + var type = UnixArgsUtil.ARGS.kvalue('type', dvalue('GLOBAL_CA_CONFIG.defaults.' + ty + '.type') || dvalue('GLOBAL_CA_CONFIG.defaults._.type')); + var keyLength = UnixArgsUtil.ARGS.kvalue('keyLength', 0); + var kpt = KeyPairGenerateTool.instance(); + + if (type.toUpperCase() == 'RSA') { + kpt.rsa(); + if (keyLength == 0) { + kpt.keyLength(dvalue('GLOBAL_CA_CONFIG.defaults.' + ty + '.keyLength.RSA') || dvalue('GLOBAL_CA_CONFIG.defaults._.keyLength.RSA')); + } + } else if (type.toUpperCase() == 'EC') { + kpt.ec(); + if (keyLength == 0) { + kpt.keyLength(dvalue('GLOBAL_CA_CONFIG.defaults.' + ty + '.keyLength.EC') || dvalue('GLOBAL_CA_CONFIG.defaults._.keyLength.EC')); + } + } else { + println(colorPrint.fail.render('[FAIL]') + 'Unknown type: ' + type); + } + if (keyLength < 0) { + println(colorPrint.fail.render('[FAIL]') + 'Key length invalid: ' + keyLength); + } else if (keyLength > 0) { + kpt.keyLength(keyLength); + } + + return [type, keyLength, kpt.generate()]; +}; + +var displayLimitChars = (str) => { + if (str.length < 80) { + return str; + } + return str.substring(0, 87) + '...'; +}; + +var listCerts = (dir) => { + $ARRAY(dir.listFiles()).forEach((d) => { + var fileCert = $$.file(d, 'cert.pem'); + if (!fileCert.exists()) { + println(colorPrint.warning.render('[WARN]') + 'No cert found in: ' + d.getName()); + return; + } + var certs = X509CertUtil.parseX509CertificateList($$.rFile(fileCert).bytes()); + if ((certs == null) || (certs.size() == 0)) { + println(colorPrint.warning.render('[WARN]') + 'No cert found in: ' + fileCert); + return; + } else if (certs.size() > 1) { + println(colorPrint.warning.render('[WARN]') + 'More than one certs found in: ' + fileCert); + return; + } + var cert = certs.get(0); + var isValid = (cert.getNotBefore().getTime() <= $$.date().millis()) && (cert.getNotAfter().getTime() >= $$.date().millis()); + println(colorPrint.bold.render('CERT ID: ') + + colorPrint.underline.render(d.getName()) + + ' ' + + (isValid? colorPrint.okgreen.render('[VALID]'): colorPrint.okgreen.render('[EXPIRED]')) + + (isValid? (' left ' + colorPrint.underline.render(parseInt((cert.getNotAfter().getTime() - $$.date().millis()) / TimeUnit.DAYS.toMillis(1))) + ' day(s)'): '') + ); + println(' Subject : ' + cert.getSubjectDN()); + println(' Issuer : ' + cert.getIssuerDN()); + if ((cert.getSubjectAlternativeNames() != null) && (cert.getSubjectAlternativeNames().size() > 0)) { + println(' Alt Subject : ' + cert.getSubjectAlternativeNames()); + } + println(' NotBefore : ' + cert.getNotBefore()); + println(' NotAfter : ' + cert.getNotAfter()); + if (UnixArgsUtil.ARGS.flags().containsAny('v', 'verbose')) { + var pkLines = $STR(cert.getPublicKey()).split("\n"); + println(' PublicKey : ' + pkLines[0]); + for (var i = 1; i < pkLines.length; i++) { + println(' : ' + displayLimitChars(pkLines[i])); + } + println(' Issuer : ' + cert.getIssuerDN()); + println(' Sign Alg : ' + cert.getSigAlgName()); + // println(' Sign Alg OID : ' + cert.getSigAlgOID()); + println(' Signature : ' + displayLimitChars(Bytes.from(cert.getSignature()).asHex())); + } +}); +}; + +var writeCert = (kp, cert, dir) => { + var serialNo = Bytes.from(cert.getSerialNumber().toByteArray()).asHex().toUpperCase(); + if (serialNo.startsWith('00')) { serialNo = serialNo.substring(2); } + var dirSerialNo = $$.file(dir, serialNo); + dirSerialNo.mkdirs(); + + var filePrivKey = $$.file(dirSerialNo, 'privkey.pem'); + var filePrivKeyEncypted = $$.file(dirSerialNo, 'privkey.pem.asc'); + var filePubKey = $$.file(dirSerialNo, 'pubkey.pem'); + var fileCert = $$.file(dirSerialNo, 'cert.pem'); + + if (filePrivKey.exists() || filePrivKeyEncypted.exists() || filePubKey.exists() || fileCert.exists()) { + println(colorPrint.fail.render('[FAIL]') + 'Serial number already exsists: ' + serialNo); + return; + } + + $$.rFile(filePrivKey).write(PEMUtil.printPEM('PRIVATE KEY', kp.getPrivate().getEncoded())); + $$.rFile(filePubKey).write(PEMUtil.printPEM('PUBLIC KEY', kp.getPublic().getEncoded())); + $$.rFile(fileCert).write(PEMUtil.printPEM('CERTIFICATE', cert.getEncoded())); + + gpgEncryptArmor(dvalue('GLOBAL_CA_CONFIG.gpgKeyId') || '6FAFC0E0170985AA71545483C794B1646A886CD6', filePrivKey.getPath(), filePrivKeyEncypted.getPath()); + + if (!filePrivKeyEncypted.exists()) { + println(colorPrint.fail.render('[FAIL]') + 'Encrypt private key failed: ' + filePrivKey); + return; + } + filePrivKey.delete(); + + if (UnixArgsUtil.ARGS.flags().containsAny('v', 'verbose')) { + println('[INFO] Public key:'); + println(kp.getPublic()); + println('[INFO] Certificate:'); + println(cert); + } + + println(colorPrint.okgreen.render('[SUCCESS]') + 'Certificate created: ' + serialNo + ' ---> ' + dir); +}; + +var defaultCA_JSON = { + "name": "My Private CA", + "gpgKeyId": "6FAFC0E0170985AA71545483C794B1646A886CD6", + "dirs": { + "CA": "ca", + "INTERMEDATE": "intermediate", + "SERVER": "server", + "CLIENT": "client" + }, + "defaults": { + "_": { + "type": "EC", + "keyLength": { + "RSA": 2048, + "EC": 256 + }, + "validYear": 5 + }, + "ca": { + "type": "EC", + "keyLength": { + "RSA": 4096, + "EC": 384 + }, + "validYear": 100 + }, + "intermediate": { + "validYear": 10 + } + } +}; + +var main = () => { + UnixArgsUtil.parseGlobalArgs($ARGS); + var args = UnixArgsUtil.ARGS.args(); + if (args == null || args.length != 2) { + printHelp(); + return; + } + var type = $STR(args[0]); + var command = $STR(args[1]); + + if (((type == '_') || (type == 'global')) && (command == 'init')) { + if ($$.file('ca.json').exists()) { + // println(colorPrint.okblue.render('[OK]') + 'File: ca.json already exists.'); + } else { + $$.rFile('ca.json').write(prettyJSON(defaultCA_JSON)); + println(colorPrint.okgreen.render('[SUCCESS]') + 'File: ca.json created.'); + } + } + if (!$$.file('ca.json').exists()) { + println('No file ca.json found!'); + println(''); + println('Please create ca.json first:'); + println(prettyJSON(defaultCA_JSON)); + return; + } + GLOBAL_CA_CONFIG = JSON.parse($$.rFile('ca.json').string()); + println('::::::Tiny CA programme: ' + (dvalue('GLOBAL_CA_CONFIG.name') || 'Unnamed CA') + ':'); + + if ((type == '_') || (type == 'global')) { + if (command == 'init') { + var tobeCreatedDirs = [dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca', + dvalue('GLOBAL_CA_CONFIG.dirs.INTERMEDATE') || 'intermediate', + dvalue('GLOBAL_CA_CONFIG.dirs.SERVER') || 'server', + dvalue('GLOBAL_CA_CONFIG.dirs.CLIENT') || 'client']; + + tobeCreatedDirs.forEach((e) => { + var f = $$.file(e); + if (f.exists()) { + if (f.isDirectory()) { + println(colorPrint.okblue.render('[OK]') + 'Directory: ' + e + ' already exists.'); + } else { + println(colorPrint.fail.render('[FAIL]') + 'File?: ' + e + ' exists, but not directory!'); + } + } else { + f.mkdirs(); + println(colorPrint.okgreen.render('[SUCCESS]') + 'Directory: ' + e + ' created.'); + } + }); + println(colorPrint.okgreen.render('[DONE]') + 'Global init finished.'); + } else if (command == 'list') { + println('[CA]' + ' list:'); + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca')); + println(); + println('[INTERMEDIATE]' + ' list:'); + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.INTERMEDIATE') || 'intermediate')); + println(); + println('[SERVER]' + ' list:'); + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.SERVER') || 'server')); + println(); + println('[CLIENT]' + ' list:'); + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CLIENT') || 'client')); + } + } else if (type == 'ca') { + if (command == 'create') { + var typeKeyLengthKP = getTypeKeyLengthKeyPair('ca'); + var type = typeKeyLengthKP[0]; + var keyLength = typeKeyLengthKP[1]; + var kp = typeKeyLengthKP[2]; + var subject = UnixArgsUtil.ARGS.kvalue('subject', '').replaceAll('__', ' '); + if (subject == '') { + println(colorPrint.fail.render('[FAIL]') + 'Subject cannot be null.'); + return; + } + var validYear = UnixArgsUtil.ARGS.kvalue('validYear', dvalue('GLOBAL_CA_CONFIG.defaults.ca.validYear') || dvalue('GLOBAL_CA_CONFIG.defaults._.validYear') || 100); + + var cert = CertificateAuthority + .instance() + .validYears(validYear) + .subject(subject) + .certPubKey(kp.getPublic()) + .signPrivKey(kp.getPrivate()) + .createCA(); + + writeCert(kp, cert, dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca'); + } else if (command == 'list') { + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca')); + } else if (command == 'delete') { + println(colorPrint.fail.render('[FAIL]') + 'Not implemented: ' + command); + } else { + println(colorPrint.fail.render('[FAIL]') + 'Unknow command: ' + command); + printHelp(); + } + } else if (type == 'intermediate') { + if (command == 'create') { + var typeKeyLengthKP = getTypeKeyLengthKeyPair('intermediate'); + var type = typeKeyLengthKP[0]; + var keyLength = typeKeyLengthKP[1]; + var kp = typeKeyLengthKP[2]; + var subject = UnixArgsUtil.ARGS.kvalue('subject', '').replaceAll('__', ' '); + if (subject == '') { + println(colorPrint.fail.render('[FAIL]') + 'Subject cannot be null.'); + return; + } + var validYear = UnixArgsUtil.ARGS.kvalue('validYear', dvalue('GLOBAL_CA_CONFIG.defaults.intermediate.validYear') || dvalue('GLOBAL_CA_CONFIG.defaults._.validYear') || 20); + var certId = UnixArgsUtil.ARGS.kvalue('certId'); + if (certId == null) { + println(colorPrint.fail.render('[FAIL]') + 'Cert ID cannot be null.'); + return; + } + var dirCA = $$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca'); + var fileCACert = $$.file(dirCA, certId, "cert.pem"); + var fileCAPrivKeyEncrypted = $$.file(dirCA, certId, "privkey.pem.asc"); + + if (!(fileCACert.exists()) || !fileCAPrivKeyEncrypted.exists()) { + println(colorPrint.fail.render('[FAIL]') + 'Cert ID not exists: ' + certId); + return; + } + var signCert = X509CertUtil.parseX509CertificateList($$.rFile(fileCACert).bytes()).get(0); + var privKeyVal; + try { + privKeyVal = gpgDecrypt(fileCAPrivKeyEncrypted.getPath()); + } catch(ex) { + println(colorPrint.fail.render('[FAIL]') + 'Decrypt private key failed: ' + fileCAPrivKeyEncrypted); + return; + } + var signPrivKey = new PrivateKeyParseTool(new BufferedReader(new StringReader(privKeyVal))).read(); + + var cert = CertificateAuthority + .instance() + .validYears(validYear) + .subject(subject) + .certPubKey(kp.getPublic()) + .signCert(signCert) + .signPrivKey(signPrivKey) + .createIntermediateCert(); + + writeCert(kp, cert, dvalue('GLOBAL_CA_CONFIG.dirs.INTERMEDATE') || 'intermediate'); + } else if (command == 'list') { + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.INTERMEDATE') || 'intermediate')); + } else if (command == 'delete') { + println(colorPrint.fail.render('[FAIL]') + 'Not implemented: ' + command); + } else { + println(colorPrint.fail.render('[FAIL]') + 'Unknow command: ' + command); + printHelp(); + } + } else if (type == 'server') { + if (command == 'create') { + var typeKeyLengthKP = getTypeKeyLengthKeyPair('server'); + var type = typeKeyLengthKP[0]; + var keyLength = typeKeyLengthKP[1]; + var kp = typeKeyLengthKP[2]; + var subject = UnixArgsUtil.ARGS.kvalue('subject', '').replaceAll('__', ' '); + if (subject == '') { + println(colorPrint.fail.render('[FAIL]') + 'Subject cannot be null.'); + return; + } + var dnsName = UnixArgsUtil.ARGS.kvalue('dnsName', ''); + if (dnsName == '') { + println(colorPrint.fail.render('[FAIL]') + 'DNSName cannot be null.'); + return; + } + var validYear = UnixArgsUtil.ARGS.kvalue('validYear', dvalue('GLOBAL_CA_CONFIG.defaults.client.validYear') || dvalue('GLOBAL_CA_CONFIG.defaults._.validYear') || 5); + var certId = UnixArgsUtil.ARGS.kvalue('certId'); + if (certId == null) { + println(colorPrint.fail.render('[FAIL]') + 'Cert ID cannot be null.'); + return; + } + var dirCA = $$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca'); + var dirIntermediate = $$.file(dvalue('GLOBAL_CA_CONFIG.dirs.INTERMEDATE') || 'intermediate'); + var fileCACert; + var fileCAPrivKeyEncrypted; + if ($$.file(dirIntermediate, certId, "cert.pem").exists()) { + fileCACert = $$.file(dirIntermediate, certId, "cert.pem"); + fileCAPrivKeyEncrypted = $$.file(dirIntermediate, certId, "privkey.pem.asc"); + } else { + fileCACert = $$.file(dirCA, certId, "cert.pem"); + fileCAPrivKeyEncrypted = $$.file(dirCA, certId, "privkey.pem.asc"); + } + + if (!(fileCACert.exists()) || !fileCAPrivKeyEncrypted.exists()) { + println(colorPrint.fail.render('[FAIL]') + 'Cert ID not exists: ' + certId); + return; + } + var signCert = X509CertUtil.parseX509CertificateList($$.rFile(fileCACert).string()).get(0); + var privKeyVal; + try { + privKeyVal = gpgDecrypt(fileCAPrivKeyEncrypted.getPath()); + } catch(ex) { + println(colorPrint.fail.render('[FAIL]') + 'Decrypt private key failed: ' + fileCAPrivKeyEncrypted); + return; + } + var signPrivKey = new PrivateKeyParseTool(new BufferedReader(new StringReader(privKeyVal))).read(); + + var cert = CertificateAuthority + .instance() + .validYears(validYear) + .subject(subject) + .certPubKey(kp.getPublic()) + .signCert(signCert) + .signPrivKey(signPrivKey) + .createServerCert($$.asList(dnsName.split(/,/g))); + + writeCert(kp, cert, dvalue('GLOBAL_CA_CONFIG.dirs.SERVER') || 'server'); + } else if (command == 'list') { + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.SERVER') || 'server')); + } else if (command == 'delete') { + println(colorPrint.fail.render('[FAIL]') + 'Not implemented: ' + command); + } else { + println(colorPrint.fail.render('[FAIL]') + 'Unknow command: ' + command); + printHelp(); + } + } else if (type == 'client') { + if (command == 'create') { + var typeKeyLengthKP = getTypeKeyLengthKeyPair('client'); + var type = typeKeyLengthKP[0]; + var keyLength = typeKeyLengthKP[1]; + var kp = typeKeyLengthKP[2]; + var subject = UnixArgsUtil.ARGS.kvalue('subject', '').replaceAll('__', ' '); + if (subject == '') { + println(colorPrint.fail.render('[FAIL]') + 'Subject cannot be null.'); + return; + } + var validYear = UnixArgsUtil.ARGS.kvalue('validYear', dvalue('GLOBAL_CA_CONFIG.defaults.client.validYear') || dvalue('GLOBAL_CA_CONFIG.defaults._.validYear') || 5); + var certId = UnixArgsUtil.ARGS.kvalue('certId'); + if (certId == null) { + println(colorPrint.fail.render('[FAIL]') + 'Cert ID cannot be null.'); + return; + } + var dirCA = $$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CA') || 'ca'); + var dirIntermediate = $$.file(dvalue('GLOBAL_CA_CONFIG.dirs.INTERMEDATE') || 'intermediate'); + var fileCACert; + var fileCAPrivKeyEncrypted; + if ($$.file(dirIntermediate, certId, "cert.pem").exists()) { + fileCACert = $$.file(dirIntermediate, certId, "cert.pem"); + fileCAPrivKeyEncrypted = $$.file(dirIntermediate, certId, "privkey.pem.asc"); + } else { + fileCACert = $$.file(dirCA, certId, "cert.pem"); + fileCAPrivKeyEncrypted = $$.file(dirCA, certId, "privkey.pem.asc"); + } + + if (!(fileCACert.exists()) || !fileCAPrivKeyEncrypted.exists()) { + println(colorPrint.fail.render('[FAIL]') + 'Cert ID not exists: ' + certId); + return; + } + var signCert = X509CertUtil.parseX509CertificateList($$.rFile(fileCACert).bytes()).get(0); + var privKeyVal; + try { + privKeyVal = gpgDecrypt(fileCAPrivKeyEncrypted.getPath()); + } catch(ex) { + println(colorPrint.fail.render('[FAIL]') + 'Decrypt private key failed: ' + fileCAPrivKeyEncrypted); + return; + } + var signPrivKey = new PrivateKeyParseTool(new BufferedReader(new StringReader(privKeyVal))).read(); + + var cert = CertificateAuthority + .instance() + .validYears(validYear) + .subject(subject) + .certPubKey(kp.getPublic()) + .signCert(signCert) + .signPrivKey(signPrivKey) + .createClientCert(); + + writeCert(kp, cert, dvalue('GLOBAL_CA_CONFIG.dirs.CLIENT') || 'client'); + } else if (command == 'list') { + listCerts($$.file(dvalue('GLOBAL_CA_CONFIG.dirs.CLIENT') || 'client')); + } else if (command == 'delete') { + println(colorPrint.fail.render('[FAIL]') + 'Not implemented: ' + command); + } else { + println(colorPrint.fail.render('[FAIL]') + 'Unknow command: ' + command); + printHelp(); + } + } +}; + +main(); diff --git a/scripts/trash.js b/scripts/trash.js new file mode 100644 index 0000000..735d139 --- /dev/null +++ b/scripts/trash.js @@ -0,0 +1,25 @@ +#! /usr/bin/env runjs + +var argsjs = require('component-args.js'); + +var main = () => { + var args = argsjs.parseDefARGs(); + if (args.length == 0) { + xprintln('[ERROR] Need args.'); + return; + } + + $ARR(args).forEach((f) => { + var fi = $$.file(f); + if (!(fi.exists())) { + xprintln('[WARN] File not exists: ' + f); + } else { + var fn = fi.getName(); + var trashDestFile = $$.file('~/.Trash/', fn + ".removed." + $$.date().fmt('yyyy_MM_dd_HH_mm_ss_SSSS').format($$.date().today())); + xprintln('[INFO] Move file: ' + fi + ' --> ' + trashDestFile); + java.nio.file.Files.move(fi.toPath(), trashDestFile.toPath()); + } + }); +}; + +main(); diff --git a/scripts/updatelibs.js b/scripts/updatelibs.js new file mode 100644 index 0000000..39249ba --- /dev/null +++ b/scripts/updatelibs.js @@ -0,0 +1,65 @@ +#! /usr/bin/env runjs +var RFile = Packages.me.hatter.tools.commons.io.RFile; + +var REPO = 'https://repo.examp1e.org/'; +var HPKP = 'YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg='; + +var main = () => { + + var libDir = $$.file('lib').exists()? $$.file('lib'): $$.file('libs'); + if (!libDir.exists()) { + xprintln('[ERROR] Dir lib or libs not exists!'); + return; + } + + println('- Load file: ' + REPO + 'files.js'); + var filesJS = $STR($$.httpTool().hpkp(HPKP).url(REPO + 'files.js').read()); + var filesJSON = JSON.parse(filesJS.substring(filesJS.indexOf('['))); + var filesSha1Map = filesJSON.toMap((e) => { + return [e[2], e[3]]; + }); + var filesSizeMap = filesJSON.toMap((e) => { + return [e[2], e[0]]; + }); + + var fileUpdated = []; + $ARRAY(libDir.list()).forEach((f) => { + var fn = $STR(f); + var remoteFnSha1 = $STR(filesSha1Map.get(fn)); + if (remoteFnSha1 == null) { + println('- SKIP file: ' + f); + return; + } + + var fi = $$.file(libDir, f); + var fiSha1 = $STR($$.digests().sha1().digest(RFile.from(fi).bytes()).asHex()); + + if (fiSha1 == remoteFnSha1) { + println('- SHA1 check success: ' + f); + } else { + println('+ SHA1 check failed: ' + f); + println('++ REMOTE:' + remoteFnSha1 + ' LOCAL: ' + fiSha1); + println('++ Load file from: ' + REPO + f + ', size: ' + filesSizeMap.get(fn)); + var counter = new Packages.me.hatter.tools.commons.io.DefaultRollCounter().prefix('++ Downloading: '); + var fBytes = $$.httpTool().hpkp(HPKP).url(REPO + f).readBytes(counter); + var downloadSha1 = $STR($$.digests().sha1().digest(fBytes).asHex()); + if (downloadSha1 == remoteFnSha1) { + fileUpdated.push(fn + ' - ' + remoteFnSha1); + RFile.from(fi).write(fBytes); + } else { + println('+ ERROR! SHA1 mis-match, Should be: ' + remoteFnSha1 + ', Actural is: ' + downloadSha1); + } + } + }); + + if (fileUpdated.length > 0) { + println(); + println('Total ' + fileUpdated.length + ' file(s) updated:'); + fileUpdated.forEach((f) => { + println('- ' + f); + }); + } +}; + +main(); + diff --git a/scripts/viewjson.js b/scripts/viewjson.js new file mode 100644 index 0000000..9f088cb --- /dev/null +++ b/scripts/viewjson.js @@ -0,0 +1,37 @@ +#! /usr/bin/env runjs + +var argsEx = require('component-args.js'); + +var System = java.lang.System; +var FastJSON = Packages.com.alibaba.fastjson.JSON; +var RStream = Packages.me.hatter.tools.commons.io.RStream; + +var main = () => { + var args = argsEx.parseDefARGs(['h', 'help', 'n']); + if (args.flg('h', 'help')) { + println('viewjson.js [FLAGS] [FILENAME]'); + println(' -h, --help Print help'); + println(' -n Do not print new line at last') + return; + } + var json = null; + if (args.length < 1) { + json = RStream.from(System.in).string(); + } else { + var j = $$.file(args[0]); + if (!(j.exists())) { + xprintln('[ERROR] File not exists: ' + j); + return; + } + json = $$.rFile(j).string(); + } + + try { + var formatedJSON = FastJSON.toJSONString($$.parseJSON(json), true).replaceAll('\t', ' '); + if (args.flg('n')) { print(formatedJSON) } else { println(formatedJSON); } + } catch (e) { + xprintln('[ERROR] Parse JSON failed.'); + } +}; + +main();