/** * @fileoverview Package-private helpers for the installer. */ 'use strict' var cp = require('child_process') var fs = require('fs-extra') var hasha = require('hasha') var helper = require('./phantomjs') var kew = require('kew') var path = require('path') var DEFAULT_CDN = 'https://github.com/Medium/phantomjs/releases/download/v2.1.1' var libPath = __dirname /** * Given a lib/location file of a PhantomJS previously installed with NPM, * is there a valid PhantomJS binary at this lib/location. * @return {Promise} resolved location of phantomjs binary on success */ function findValidPhantomJsBinary(libPath) { return kew.fcall(function () { var libModule = require(libPath) if (libModule.location && getTargetPlatform() == libModule.platform && getTargetArch() == libModule.arch) { var resolvedLocation = path.resolve(path.dirname(libPath), libModule.location) if (fs.statSync(resolvedLocation)) { return checkPhantomjsVersion(resolvedLocation).then(function (matches) { if (matches) { return kew.resolve(resolvedLocation) } }) } } return false }).fail(function () { return false }) } /** * Check to make sure a given binary is the right version. * @return {kew.Promise.} */ function checkPhantomjsVersion(phantomPath) { console.log('Found PhantomJS at', phantomPath, '...verifying') return kew.nfcall(cp.execFile, phantomPath, ['--version']).then(function (stdout) { var version = stdout.trim() if (helper.version == version) { return true } else { console.log('PhantomJS detected, but wrong version', stdout.trim(), '@', phantomPath + '.') return false } }).fail(function (err) { console.error('Error verifying phantomjs, continuing', err) return false }) } /** * Writes the location file with location and platform/arch metadata about the * binary. */ function writeLocationFile(location) { console.log('Writing location.js file') if (getTargetPlatform() === 'win32') { location = location.replace(/\\/g, '\\\\') } var platform = getTargetPlatform() var arch = getTargetArch() var contents = 'module.exports.location = "' + location + '"\n' if (/^[a-zA-Z0-9]*$/.test(platform) && /^[a-zA-Z0-9]*$/.test(arch)) { contents += 'module.exports.platform = "' + getTargetPlatform() + '"\n' + 'module.exports.arch = "' + getTargetArch() + '"\n' } fs.writeFileSync(path.join(libPath, 'location.js'), contents) } /** * @return {?{url: string, checksum: string}} Get the download URL and expected * SHA-256 checksum for phantomjs. May return null if no download url exists. */ function getDownloadSpec() { var cdnUrl = process.env.npm_config_phantomjs_cdnurl || process.env.PHANTOMJS_CDNURL || DEFAULT_CDN var downloadUrl = cdnUrl + '/phantomjs-' + helper.version + '-' var checksum = '' var platform = getTargetPlatform() var arch = getTargetArch() if (platform === 'linux' && arch === 'x64') { downloadUrl += 'linux-x86_64.tar.bz2' checksum = '86dd9a4bf4aee45f1a84c9f61cf1947c1d6dce9b9e8d2a907105da7852460d2f' } else if (platform === 'linux' && arch == 'ia32') { downloadUrl += 'linux-i686.tar.bz2' checksum = '80e03cfeb22cc4dfe4e73b68ab81c9fdd7c78968cfd5358e6af33960464f15e3' } else if (platform === 'darwin') { downloadUrl += 'macosx.zip' checksum = '538cf488219ab27e309eafc629e2bcee9976990fe90b1ec334f541779150f8c1' } else if (platform === 'win32') { downloadUrl += 'windows.zip' checksum = 'd9fb05623d6b26d3654d008eab3adafd1f6350433dfd16138c46161f42c7dcc8' } else { return null } return {url: downloadUrl, checksum: checksum} } /** * Check to make sure that the file matches the checksum. * @param {string} fileName * @param {string} checksum * @return {Promise.} */ function verifyChecksum(fileName, checksum) { return kew.resolve(hasha.fromFile(fileName, {algorithm: 'sha256'})).then(function (hash) { var result = checksum == hash if (result) { console.log('Verified checksum of previously downloaded file') } else { console.log('Checksum did not match') } return result }).fail(function (err) { console.error('Failed to verify checksum: ', err) return false }) } /** * @return {string} */ function getTargetPlatform() { return process.env.PHANTOMJS_PLATFORM || process.platform } /** * @return {string} */ function getTargetArch() { return process.env.PHANTOMJS_ARCH || process.arch } module.exports = { checkPhantomjsVersion: checkPhantomjsVersion, getDownloadSpec: getDownloadSpec, getTargetPlatform: getTargetPlatform, getTargetArch: getTargetArch, findValidPhantomJsBinary: findValidPhantomJsBinary, verifyChecksum: verifyChecksum, writeLocationFile: writeLocationFile }