From 7fb33c6813e5b68e3eb70687d2f8fae46ef62818 Mon Sep 17 00:00:00 2001 From: Daniel Scalzi Date: Sat, 31 Mar 2018 20:45:24 -0400 Subject: [PATCH] Rough completion of JRE downloads from oracle. Mojang fallback cannot be implemented due to limitations of decompressing large lzma files in node.js. This can probably be worked around by packaging with some command line binary, but it honestly it not worth it. --- app/assets/js/assetguard.js | 151 ++++++++++++++++++++++++++--------- package-lock.json | 155 +++++++++++++++++++++++++++++++++--- package.json | 1 + 3 files changed, 260 insertions(+), 47 deletions(-) diff --git a/app/assets/js/assetguard.js b/app/assets/js/assetguard.js index 309498e..5f44af9 100644 --- a/app/assets/js/assetguard.js +++ b/app/assets/js/assetguard.js @@ -32,6 +32,7 @@ const mkpath = require('mkdirp'); const path = require('path') const Registry = require('winreg') const request = require('request') +const targz = require('targz') // Constants const PLATFORM_MAP = { @@ -557,6 +558,23 @@ class AssetGuard extends EventEmitter { }) } + /** + * Load Mojang's launcher.json file. + * + * @returns {Promise.} Promise which resolves to Mojang's launcher.json object. + */ + static loadMojangLauncherData(){ + return new Promise((resolve, reject) => { + request.get('https://launchermeta.mojang.com/mc/launcher.json', (err, resp, body) => { + if(err){ + resolve(null) + } else { + resolve(JSON.parse(body)) + } + }) + }) + } + /** * Validates that a Java binary is at least 64 bit. This makes use of the non-standard * command line option -XshowSettings:properties. The output of this contains a property, @@ -717,15 +735,15 @@ class AssetGuard extends EventEmitter { * Higher versions > Lower versions * If versions are equal, JRE > JDK. * - * @returns {string} The root path of a valid x64 Java installation. If none are - * found, null is returned. + * @returns {Promise.} A Promise which resolves to the root path of a valid + * x64 Java installation. If none are found, null is returned. */ static async _win32JavaValidate(){ // Get possible paths from the registry. const pathSet = await AssetGuard._scanRegistry() - console.log(Array.from(pathSet)) // DEBUGGING + //console.log(Array.from(pathSet)) // DEBUGGING // Validate JAVA_HOME const jHome = AssetGuard._scanJavaHome() @@ -736,7 +754,7 @@ class AssetGuard extends EventEmitter { // Convert path set to an array for processing. let pathArr = Array.from(pathSet) - console.log(pathArr) // DEBUGGING + //console.log(pathArr) // DEBUGGING // Sorts array. Higher version numbers preceed lower. JRE preceeds JDK. pathArr = pathArr.sort((a, b) => { @@ -751,7 +769,7 @@ class AssetGuard extends EventEmitter { } }) - console.log(pathArr) // DEBUGGING + //console.log(pathArr) // DEBUGGING // Validate that the binary is actually x64. for(let i=0; i { const name = version + '.json' const url = 'https://s3.amazonaws.com/Minecraft.Download/versions/' + version + '/' + name const versionPath = path.join(self.basePath, 'versions', version) const versionFile = path.join(versionPath, name) if(!fs.existsSync(versionFile) || force){ //This download will never be tracked as it's essential and trivial. - request.head(url, function(err, res, body){ - console.log('Preparing download of ' + version + ' assets.') - mkpath.sync(versionPath) - const stream = request(url).pipe(fs.createWriteStream(versionFile)) - stream.on('finish', function(){ - fulfill(JSON.parse(fs.readFileSync(versionFile))) - }) + console.log('Preparing download of ' + version + ' assets.') + mkpath.sync(versionPath) + const stream = request(url).pipe(fs.createWriteStream(versionFile)) + stream.on('finish', () => { + resolve(JSON.parse(fs.readFileSync(versionFile))) }) } else { - fulfill(JSON.parse(fs.readFileSync(versionFile))) + resolve(JSON.parse(fs.readFileSync(versionFile))) } }) } - loadMojangLauncherData(){ - //https://launchermeta.mojang.com/mc/launcher.json - } - // Asset (Category=''') Validation Functions // #region @@ -1193,29 +1210,91 @@ class AssetGuard extends EventEmitter { // Java (Category=''') Validation (download) Functions // #region - async _enqueueOracleJRE(dir){ - const verData = await AssetGuard._latestJREOracle() + _enqueueOracleJRE(dir){ + return new Promise((resolve, reject) => { + AssetGuard._latestJREOracle().then(verData => { + if(verData != null){ - const combined = verData.uri + PLATFORM_MAP[process.platform] - const name = combined.substring(combined.lastIndexOf('/')+1) - const fDir = path.join(dir, name) + const combined = verData.uri + PLATFORM_MAP[process.platform] + + const opts = { + url: combined, + headers: { + 'Cookie': 'oraclelicense=accept-securebackup-cookie' + } + } + + request.head(opts, (err, resp, body) => { + if(err){ + resolve(false) + } else { + const name = combined.substring(combined.lastIndexOf('/')+1) + const fDir = path.join(dir, name) + const jre = new Asset(name, null, resp.headers['content-length'], opts, fDir) + this.java = new DLTracker([jre], jre.size, a => { + targz.decompress({ + src: a.to, + dest: dir + }, err => { + if(err){ + console.log(err) + } else { + fs.unlink(a.to, err => { + if(err){ + console.log(err) + } + }) + } + }) + }) + resolve(true) + } + }) - const opts = { - url: combined, - headers: { - 'Cookie': 'oraclelicense=accept-securebackup-cookie' - } - } + } else { + resolve(false) + } + }) + }) - if(verData != null){ - const jre = new Asset(name, null, 0, opts, fDir) - this.java = new DLTracker([jre], jre.size) - return true - } else { - return false - } } + /*_enqueueMojangJRE(dir){ + return new Promise((resolve, reject) => { + // Mojang does not host the JRE for linux. + if(process.platform === 'linux'){ + resolve(false) + } + AssetGuard.loadMojangLauncherData().then(data => { + if(data != null) { + + try { + const mJRE = data[Library.mojangFriendlyOS()]['64'].jre + const url = mJRE.url + + request.head(url, (err, resp, body) => { + if(err){ + resolve(false) + } else { + const name = url.substring(url.lastIndexOf('/')+1) + const fDir = path.join(dir, name) + const jre = new Asset('jre' + mJRE.version, mJRE.sha1, resp.headers['content-length'], url, fDir) + this.java = new DLTracker([jre], jre.size, a => { + fs.readFile(a.to, (err, data) => { + // Data buffer needs to be decompressed from lzma, + // not really possible using node.js + }) + }) + } + }) + } catch (err){ + resolve(false) + } + + } + }) + }) + }*/ // #endregion diff --git a/package-lock.json b/package-lock.json index f08b42c..407b995 100644 --- a/package-lock.json +++ b/package-lock.json @@ -241,6 +241,44 @@ "tweetnacl": "0.14.5" } }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.5", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", @@ -430,6 +468,11 @@ "supports-color": "5.3.0" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, "chromium-pickle-js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", @@ -600,8 +643,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "create-error-class": { "version": "3.0.2", @@ -1174,6 +1216,14 @@ "mime": "2.2.0" } }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, "env-paths": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", @@ -1523,8 +1573,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", @@ -2006,7 +2055,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -2196,8 +2244,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress-stream": { "version": "1.2.0", @@ -2215,6 +2262,15 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -2661,6 +2717,85 @@ "has-flag": "3.0.0" } }, + "tar-fs": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.0.tgz", + "integrity": "sha512-I9rb6v7mjWLtOfCau9eH5L7sLJyU2BnxtEZRQ5Mt+eRKmf1F0ohXmT/Jc3fr52kDvjJ/HV5MH3soQfPL5bQ0Yg==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.5.5" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "requires": { + "bl": "1.2.2", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.5", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "targz": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/targz/-/targz-1.0.1.tgz", + "integrity": "sha1-j3alI2lM3t+7XWCkB2/27uzFOY8=", + "requires": { + "tar-fs": "1.16.0" + } + }, "temp-file": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.1.1.tgz", @@ -2823,8 +2958,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.2.1", @@ -2918,8 +3052,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "2.3.0", diff --git a/package.json b/package.json index a7680e6..646ea0c 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "ejs-electron": "^2.0.1", "jquery": "^3.3.1", "request-promise-native": "^1.0.5", + "targz": "^1.0.1", "uuid": "^3.2.1", "winreg": "^1.2.4" },