Addes sha1 hash validation for all download processes - code is pending a final review/cleanup

This commit is contained in:
Daniel Scalzi 2017-04-28 14:52:24 -04:00
parent cf0afeb957
commit b01f652d8c
2 changed files with 94 additions and 82 deletions

View File

@ -51,17 +51,20 @@ exports.downloadClient = function(versionData, basePath){
const url = clientData['url'] const url = clientData['url']
const size = clientData['size'] const size = clientData['size']
const version = versionData['id'] const version = versionData['id']
const sha1 = clientData['sha1']
const targetPath = path.join(basePath, 'versions', version) const targetPath = path.join(basePath, 'versions', version)
const targetFile = version + '.jar' const targetFile = version + '.jar'
request.head(url, function(err, res, body){ if(!validateLocalIntegrity(path.join(targetPath, targetFile), 'sha1', sha1)){
console.log('Downloading ' + version + ' client..') request.head(url, function(err, res, body){
mkpath.sync(targetPath) console.log('Downloading ' + version + ' client..')
const stream = request(url).pipe(fs.createWriteStream(path.join(targetPath, targetFile))) mkpath.sync(targetPath)
stream.on('finish', function(){ const stream = request(url).pipe(fs.createWriteStream(path.join(targetPath, targetFile)))
console.log('Finished downloading ' + version + ' client.') stream.on('finish', function(){
console.log('Finished downloading ' + version + ' client.')
})
}) })
}) }
} }
exports.downloadLogConfig = function(versionData, basePath){ exports.downloadLogConfig = function(versionData, basePath){
@ -69,45 +72,51 @@ exports.downloadLogConfig = function(versionData, basePath){
const client = logging['client'] const client = logging['client']
const file = client['file'] const file = client['file']
const version = versionData['id'] const version = versionData['id']
const sha1 = file['sha1']
const targetPath = path.join(basePath, 'assets', 'log_configs') const targetPath = path.join(basePath, 'assets', 'log_configs')
const name = file['id'] const name = file['id']
const url = file['url'] const url = file['url']
request.head(url, function(err, res, body){ if(!validateLocalIntegrity(path.join(targetPath, name), 'sha1', sha1)){
console.log('Downloading ' + version + ' log config..') request.head(url, function(err, res, body){
mkpath.sync(targetPath) console.log('Downloading ' + version + ' log config..')
const stream = request(url).pipe(fs.createWriteStream(path.join(targetPath, name))) mkpath.sync(targetPath)
stream.on('finish', function(){ const stream = request(url).pipe(fs.createWriteStream(path.join(targetPath, name)))
console.log('Finished downloading ' + version + ' log config..') stream.on('finish', function(){
console.log('Finished downloading ' + version + ' log config..')
})
}) })
}) }
} }
exports.downloadLibraries = function(versionData, basePath){ exports.downloadLibraries = function(versionData, basePath){
const libArr = versionData['libraries'] const libArr = versionData['libraries']
const libPath = path.join(basePath, 'libraries') const libPath = path.join(basePath, 'libraries')
console.log(libArr)
async.eachLimit(libArr, 1, function(lib, cb){ async.eachLimit(libArr, 1, function(lib, cb){
if(validateRules(lib['rules'])){ if(validateRules(lib['rules'])){
if(lib['natives'] == null){ if(lib['natives'] == null){
const dlInfo = lib['downloads'] const dlInfo = lib['downloads']
const artifact = dlInfo['artifact'] const artifact = dlInfo['artifact']
const sha1 = artifact['sha1']
const libSize = artifact['size'] const libSize = artifact['size']
const to = path.join(libPath, artifact['path']) const to = path.join(libPath, artifact['path'])
const from = artifact['url'] const from = artifact['url']
if(!validateLocalIntegrity(to, 'sha1', sha1)){
mkpath.sync(path.join(to, "..")) mkpath.sync(path.join(to, ".."))
let req = request(from) let req = request(from)
let writeStream = fs.createWriteStream(to) let writeStream = fs.createWriteStream(to)
req.pipe(writeStream) req.pipe(writeStream)
let acc = 0; let acc = 0;
req.on('data', function(chunk){ req.on('data', function(chunk){
acc += chunk.length acc += chunk.length
//console.log('Progress', acc/libSize) //console.log('Progress', acc/libSize)
}) })
writeStream.on('close', function(){ writeStream.on('close', function(){
cb()
})
} else {
cb() cb()
}) }
} else { } else {
const natives = lib['natives'] const natives = lib['natives']
const opSys = mojangFriendlyOS() const opSys = mojangFriendlyOS()
@ -119,21 +128,24 @@ exports.downloadLibraries = function(versionData, basePath){
const libSize = artifact['size'] const libSize = artifact['size']
const to = path.join(libPath, artifact['path']) const to = path.join(libPath, artifact['path'])
const from = artifact['url'] const from = artifact['url']
const sha1 = artifact['sha1']
console.log(to) if(!validateLocalIntegrity(to, 'sha1', sha1)){
mkpath.sync(path.join(to, ".."))
mkpath.sync(path.join(to, "..")) let req = request(from)
let req = request(from) let writeStream = fs.createWriteStream(to)
let writeStream = fs.createWriteStream(to) req.pipe(writeStream)
req.pipe(writeStream) let acc = 0;
let acc = 0; req.on('data', function(chunk){
req.on('data', function(chunk){ acc += chunk.length
acc += chunk.length console.log('Progress', acc/libSize)
console.log('Progress', acc/libSize) })
}) writeStream.on('close', function(){
writeStream.on('close', function(){ cb()
})
} else {
cb() cb()
}) }
} }
} else { } else {
cb() cb()
@ -147,43 +159,6 @@ exports.downloadLibraries = function(versionData, basePath){
}) })
} }
validateRules = function(rules){
if(rules == null) return true
let result = true
rules.forEach(function(rule){
const action = rule['action']
const osProp = rule['os']
if(action != null){
if(osProp != null){
const osName = osProp['name']
const osMoj = mojangFriendlyOS()
if(action === 'allow'){
result = osName === osMoj
return
} else if(action === 'disallow'){
result = osName !== osMoj
return
}
}
}
})
return result
}
mojangFriendlyOS = function(){
const opSys = process.platform
if (opSys === 'darwin') {
return 'osx';
} else if (opSys === 'win32'){
return 'windows';
} else if (opSys === 'linux'){
return 'linux';
} else {
return 'unknown_os';
}
}
/** /**
* Given an index url, this function will asynchonously download the * Given an index url, this function will asynchonously download the
* assets associated with that version. * assets associated with that version.
@ -263,4 +238,41 @@ validateLocalIntegrity = function(filePath, algo, hash){
} }
} }
return false; return false;
}
validateRules = function(rules){
if(rules == null) return true
let result = true
rules.forEach(function(rule){
const action = rule['action']
const osProp = rule['os']
if(action != null){
if(osProp != null){
const osName = osProp['name']
const osMoj = mojangFriendlyOS()
if(action === 'allow'){
result = osName === osMoj
return
} else if(action === 'disallow'){
result = osName !== osMoj
return
}
}
}
})
return result
}
mojangFriendlyOS = function(){
const opSys = process.platform
if (opSys === 'darwin') {
return 'osx';
} else if (opSys === 'win32'){
return 'windows';
} else if (opSys === 'linux'){
return 'linux';
} else {
return 'unknown_os';
}
} }

View File

@ -18,16 +18,16 @@ function createWindow() {
win.setMenu(null) win.setMenu(null)
//Code for testing, marked for removal one it's properly implemented. //Code for testing, marked for removal one it's properly implemented.
const assetdl = require('./app/assets/js/assetdownload.js') /*const assetdl = require('./app/assets/js/assetdownload.js')
const basePath = path.join(__dirname, 'mcfiles') const basePath = path.join(__dirname, 'mcfiles')
const dataPromise = assetdl.parseVersionData('1.11.2', basePath) const dataPromise = assetdl.parseVersionData('1.11.2', basePath)
dataPromise.then(function(data){ dataPromise.then(function(data){
assetdl.downloadAssets(data, basePath) assetdl.downloadAssets(data, basePath)
//assetdl.downloadClient(data, basePath) assetdl.downloadClient(data, basePath)
//assetdl.downloadLogConfig(data, basePath) assetdl.downloadLogConfig(data, basePath)
//assetdl.downloadLibraries(data, basePath) assetdl.downloadLibraries(data, basePath)
//require('./app/assets/js/launchprocess.js').launchMinecraft(data, basePath) //require('./app/assets/js/launchprocess.js').launchMinecraft(data, basePath)
}) })*/
win.on('closed', () => { win.on('closed', () => {
win = null win = null