Permalink
Browse files

Check download content shasums with SHASUMS.txt. fixed npm/npm#4541

  • Loading branch information...
1 parent 0cd9f08 commit 869baee047317bd735efac7918cf063c5731195c @fengmk2 fengmk2 committed Jan 24, 2014
Showing with 83 additions and 1 deletion.
  1. +83 −1 lib/install.js
View
@@ -12,6 +12,7 @@ var fs = require('graceful-fs')
, tar = require('tar')
, rm = require('rimraf')
, path = require('path')
+ , crypto = require('crypto')
, zlib = require('zlib')
, log = require('npmlog')
, semver = require('semver')
@@ -151,6 +152,15 @@ function install (gyp, argv, callback) {
return req
}
+ function getContentSha(res, callback) {
+ var shasum = crypto.createHash('sha1')
+ res.on('data', function (chunk) {
+ shasum.update(chunk)
+ }).on('end', function () {
+ callback(null, shasum.digest('hex'))
+ })
+ }
+
function go () {
log.verbose('ensuring nodedir is created', devDir)
@@ -178,6 +188,9 @@ function install (gyp, argv, callback) {
, gunzip = zlib.createGunzip()
, extracter = tar.Extract({ path: devDir, strip: 1, filter: isValid })
+ var contentShasums = {}
+ var expectShasums = {}
+
// checks if a file to be extracted from the tarball is valid.
// only .h header files and the gyp files get extracted
function isValid () {
@@ -230,6 +243,13 @@ function install (gyp, argv, callback) {
cb(new Error(res.statusCode + ' status code downloading tarball'))
return
}
+ // content sha1
+ getContentSha(res, function (_, sha1) {
+ var filename = path.basename(tarballUrl).trim()
+ contentShasums[filename] = sha1
+ log.verbose('content sha1', filename, sha1)
+ })
+
// start unzipping and untaring
req.pipe(gunzip).pipe(extracter)
})
@@ -254,17 +274,69 @@ function install (gyp, argv, callback) {
var installVersionPath = path.resolve(devDir, 'installVersion')
fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref)
+ // download SHASUMS.txt
+ async++
+ downloadShasums(deref)
+
if (async === 0) {
// no async tasks required
cb()
}
function deref (err) {
if (err) return cb(err)
- --async || cb()
+
+ async--
+ if (!async) {
+ log.verbose('download contents shasums', JSON.stringify(contentShasums))
+ // check content shasums
+ for (var k in contentShasums) {
+ if (contentShasums[k] !== expectShasums[k]) {
+ cb(new Error(k + ' local sha1 ' + contentShasums[k] + ' not match remote ' + expectShasums[k]))
+ return
+ }
+ }
+ cb()
+ }
}
}
+ function downloadShasums(done) {
+ log.verbose('check download content sha1, need to download `SHASUMS.txt`...')
+ var shasumsPath = path.resolve(devDir, 'SHASUMS.txt')
+ , shasumsUrl = distUrl + '/v' + version + '/SHASUMS.txt'
+
+ log.verbose('`SHASUMS.txt` url', shasumsUrl)
+ var req = download(shasumsUrl)
+ if (!req) return
+ req.on('error', done)
+ req.on('response', function (res) {
+ if (res.statusCode !== 200) {
+ done(new Error(res.statusCode + ' status code downloading SHASUMS.txt'))
+ return
+ }
+
+ var chunks = [];
+ res.on('data', function (chunk) {
+ chunks.push(chunk)
+ })
+ res.on('end', function () {
+ var lines = Buffer.concat(chunks).toString().trim().split('\n')
+ lines.forEach(function (line) {
+ var items = line.trim().split(/\s+/)
+ if (items.length !== 2) return
+
+ // 0035d18e2dcf9aad669b1c7c07319e17abfe3762 ./node-v0.11.4.tar.gz
+ var name = items[1].replace(/^\.\//, '');
+ expectShasums[name] = items[0]
+ })
+
+ log.verbose('`SHASUMS.txt` data', JSON.stringify(expectShasums))
+ done()
+ })
+ })
+ }
+
function downloadNodeLib (done) {
log.verbose('on Windows; need to download `node.lib`...')
var dir32 = path.resolve(devDir, 'ia32')
@@ -293,6 +365,11 @@ function install (gyp, argv, callback) {
return
}
+ getContentSha(res, function (_, sha1) {
+ contentShasums['node.lib'] = sha1
+ log.verbose('content sha1', 'node.lib', sha1)
+ })
+
var ws = fs.createWriteStream(nodeLibPath32)
ws.on('error', cb)
req.pipe(ws)
@@ -314,6 +391,11 @@ function install (gyp, argv, callback) {
return
}
+ getContentSha(res, function (_, sha1) {
+ contentShasums['x64/node.lib'] = sha1
+ log.verbose('content sha1', 'x64/node.lib', sha1)
+ })
+
var ws = fs.createWriteStream(nodeLibPath64)
ws.on('error', cb)
req.pipe(ws)

0 comments on commit 869baee

Please sign in to comment.