123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- /*
- Copyright 2016 Mark Lee
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- 'use strict';
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
- var debug = require('debug')('sumchecker');
- var crypto = require('crypto');
- var fs = require('fs');
- var path = require('path');
- var Promise = global.Promise || require('es6-promise').Promise;
- var CHECKSUM_LINE = /^([\da-fA-F]+) ([ *])(.+)$/;
- var ErrorWithFilename = function (_Error) {
- _inherits(ErrorWithFilename, _Error);
- function ErrorWithFilename(filename) {
- _classCallCheck(this, ErrorWithFilename);
- var _this = _possibleConstructorReturn(this, (ErrorWithFilename.__proto__ || Object.getPrototypeOf(ErrorWithFilename)).call(this));
- _this.filename = filename;
- return _this;
- }
- return ErrorWithFilename;
- }(Error);
- var ChecksumMismatchError = function (_ErrorWithFilename) {
- _inherits(ChecksumMismatchError, _ErrorWithFilename);
- function ChecksumMismatchError(filename) {
- _classCallCheck(this, ChecksumMismatchError);
- var _this2 = _possibleConstructorReturn(this, (ChecksumMismatchError.__proto__ || Object.getPrototypeOf(ChecksumMismatchError)).call(this, filename));
- _this2.message = 'Generated checksum for "' + filename + '" did not match expected checksum.';
- return _this2;
- }
- return ChecksumMismatchError;
- }(ErrorWithFilename);
- var ChecksumParseError = function (_Error2) {
- _inherits(ChecksumParseError, _Error2);
- function ChecksumParseError(lineNumber, line) {
- _classCallCheck(this, ChecksumParseError);
- var _this3 = _possibleConstructorReturn(this, (ChecksumParseError.__proto__ || Object.getPrototypeOf(ChecksumParseError)).call(this));
- _this3.lineNumber = lineNumber;
- _this3.line = line;
- _this3.message = 'Could not parse checksum file at line ' + lineNumber + ': ' + line;
- return _this3;
- }
- return ChecksumParseError;
- }(Error);
- var NoChecksumFoundError = function (_ErrorWithFilename2) {
- _inherits(NoChecksumFoundError, _ErrorWithFilename2);
- function NoChecksumFoundError(filename) {
- _classCallCheck(this, NoChecksumFoundError);
- var _this4 = _possibleConstructorReturn(this, (NoChecksumFoundError.__proto__ || Object.getPrototypeOf(NoChecksumFoundError)).call(this, filename));
- _this4.message = 'No checksum found in checksum file for "' + filename + '".';
- return _this4;
- }
- return NoChecksumFoundError;
- }(ErrorWithFilename);
- var ChecksumValidator = function () {
- function ChecksumValidator(algorithm, checksumFilename, options) {
- _classCallCheck(this, ChecksumValidator);
- this.algorithm = algorithm;
- this.checksumFilename = checksumFilename;
- this.checksums = null;
- if (options && options.defaultTextEncoding) {
- this.defaultTextEncoding = options.defaultTextEncoding;
- } else {
- this.defaultTextEncoding = 'utf8';
- }
- }
- _createClass(ChecksumValidator, [{
- key: 'encoding',
- value: function encoding(binary) {
- return binary ? 'binary' : this.defaultTextEncoding;
- }
- }, {
- key: 'parseChecksumFile',
- value: function parseChecksumFile(data) {
- var that = this;
- return new Promise(function (resolve, reject) {
- debug('Parsing checksum file');
- that.checksums = {};
- var lineNumber = 0;
- data.trim().split(/[\r\n]+/).forEach(function (line) {
- lineNumber += 1;
- var result = CHECKSUM_LINE.exec(line);
- if (result === null) {
- debug('Could not parse line number ' + lineNumber);
- reject(new ChecksumParseError(lineNumber, line));
- } else {
- // destructuring isn't available until Node 6
- var filename = result[3];
- var isBinary = result[2] === '*';
- var checksum = result[1];
- that.checksums[filename] = [checksum, isBinary];
- }
- });
- debug('Parsed checksums:', that.checksums);
- resolve();
- });
- }
- }, {
- key: 'readFile',
- value: function readFile(filename, binary) {
- var _this5 = this;
- debug('Reading "' + filename + ' (binary mode: ' + binary + ')"');
- return new Promise(function (resolve, reject) {
- fs.readFile(filename, _this5.encoding(binary), function (err, data) {
- if (err) {
- reject(err);
- } else {
- resolve(data);
- }
- });
- });
- }
- }, {
- key: 'validate',
- value: function validate(baseDir, filesToCheck) {
- var _this6 = this;
- if (typeof filesToCheck === 'string') {
- filesToCheck = [filesToCheck];
- }
- return this.readFile(this.checksumFilename, false).then(this.parseChecksumFile.bind(this)).then(function () {
- return _this6.validateFiles(baseDir, filesToCheck);
- });
- }
- }, {
- key: 'validateFile',
- value: function validateFile(baseDir, filename) {
- var _this7 = this;
- return new Promise(function (resolve, reject) {
- debug('validateFile: ' + filename);
- var metadata = _this7.checksums[filename];
- if (!metadata) {
- return reject(new NoChecksumFoundError(filename));
- }
- // destructuring isn't available until Node 6
- var checksum = metadata[0];
- var binary = metadata[1];
- var fullPath = path.resolve(baseDir, filename);
- debug('Reading file with "' + _this7.encoding(binary) + '" encoding');
- var stream = fs.createReadStream(fullPath, { encoding: _this7.encoding(binary) });
- var hasher = crypto.createHash(_this7.algorithm, { defaultEncoding: 'binary' });
- hasher.on('readable', function () {
- var data = hasher.read();
- if (data) {
- var calculated = data.toString('hex');
- debug('Expected checksum: ' + checksum + '; Actual: ' + calculated);
- if (calculated === checksum) {
- resolve();
- } else {
- reject(new ChecksumMismatchError(filename));
- }
- }
- });
- stream.pipe(hasher);
- });
- }
- }, {
- key: 'validateFiles',
- value: function validateFiles(baseDir, filesToCheck) {
- var that = this;
- return Promise.all(filesToCheck.map(function (filename) {
- return that.validateFile(baseDir, filename);
- }));
- }
- }]);
- return ChecksumValidator;
- }();
- var sumchecker = function sumchecker(algorithm, checksumFilename, baseDir, filesToCheck) {
- return new ChecksumValidator(algorithm, checksumFilename).validate(baseDir, filesToCheck);
- };
- sumchecker.ChecksumMismatchError = ChecksumMismatchError;
- sumchecker.ChecksumParseError = ChecksumParseError;
- sumchecker.ChecksumValidator = ChecksumValidator;
- sumchecker.NoChecksumFoundError = NoChecksumFoundError;
- module.exports = sumchecker;
|