diff --git a/lib/gui/app.js b/lib/gui/app.js index f331bfea..8a89d0fb 100644 --- a/lib/gui/app.js +++ b/lib/gui/app.js @@ -21,7 +21,6 @@ 'use strict'; var angular = require('angular'); -const path = require('path'); const _ = require('lodash'); const app = angular.module('Etcher', [ @@ -191,9 +190,7 @@ app.controller('AppController', function( document.querySelector('body').style.display = 'initial'; this.selectImage = function(image) { - const extension = path.extname(image.path).slice(1); - - if (!_.includes(SupportedFormatsModel.getAllExtensions(), extension)) { + if (!SupportedFormatsModel.isSupportedImage(image.path)) { AnalyticsService.logEvent('Invalid image', image); return; } diff --git a/lib/gui/models/supported-formats.js b/lib/gui/models/supported-formats.js index 90a457d0..d6341985 100644 --- a/lib/gui/models/supported-formats.js +++ b/lib/gui/models/supported-formats.js @@ -27,6 +27,7 @@ const MODULE_NAME = 'Etcher.Models.SupportedFormats'; const SupportedFormats = angular.module(MODULE_NAME, []); SupportedFormats.service('SupportedFormatsModel', function() { + let self = this; /** * @summary Check if a file type is a compressed format @@ -93,6 +94,40 @@ SupportedFormats.service('SupportedFormatsModel', function() { return _.map(imageStream.supportedFileTypes, 'extension'); }; + /** + * @summary Check if an image is supported + * @function + * @public + * + * @param {String} image - image path + * @returns {Boolean} whether the image is supported + * + * if (SupportedFormatsModel.isSupportedImage('foo.iso.bz2')) { + * console.log('The image is supported!'); + * } + */ + this.isSupportedImage = function(image) { + + // We roll our own extension detection system instead of + // using `path.extname()` since that function will only + // return the last extension, while we're interested + // to check every possible extension of an image path, + // like `.tar.gz`. + + const firstDotIndex = image.indexOf('.'); + + // An image without an extension is not considered a valid image + if (firstDotIndex === -1) { + return false; + } + + const extensions = image.slice(firstDotIndex + 1).split('.'); + + return _.every(extensions, function(extension) { + return _.includes(self.getAllExtensions(), extension); + }); + }; + }); module.exports = MODULE_NAME; diff --git a/tests/gui/models/supported-formats.spec.js b/tests/gui/models/supported-formats.spec.js index 7dd631a7..a6b1495f 100644 --- a/tests/gui/models/supported-formats.spec.js +++ b/tests/gui/models/supported-formats.spec.js @@ -49,6 +49,42 @@ describe('Browser: SupportedFormats', function() { }); + describe('.isSupportedImage()', function() { + + it('should return false if the file has no extension', function() { + const isSupported = SupportedFormatsModel.isSupportedImage('/path/to/foo'); + m.chai.expect(isSupported).to.be.false; + }); + + it('should return false if the extension is not included in .getAllExtensions()', function() { + const isSupported = SupportedFormatsModel.isSupportedImage('/path/to/foo.jpg'); + m.chai.expect(isSupported).to.be.false; + }); + + it('should return true if the extension is included in .getAllExtensions()', function() { + const supportedExtensions = SupportedFormatsModel.getAllExtensions(); + const imagePath = '/path/to/foo.' + _.first(supportedExtensions); + const isSupported = SupportedFormatsModel.isSupportedImage(imagePath); + m.chai.expect(isSupported).to.be.true; + }); + + it('should return true if the extension is a supported one plus a supported compressed extensions', function() { + const nonCompressedExtension = _.first(SupportedFormatsModel.getNonCompressedExtensions()); + const compressedExtension = _.first(SupportedFormatsModel.getCompressedExtensions()); + const imagePath = '/path/to/foo.' + nonCompressedExtension + '.' + compressedExtension; + const isSupported = SupportedFormatsModel.isSupportedImage(imagePath); + m.chai.expect(isSupported).to.be.true; + }); + + it('should return false if the extension is an unsupported one plus a supported compressed extensions', function() { + const compressedExtension = _.first(SupportedFormatsModel.getCompressedExtensions()); + const imagePath = '/path/to/foo.jpg.' + compressedExtension; + const isSupported = SupportedFormatsModel.isSupportedImage(imagePath); + m.chai.expect(isSupported).to.be.false; + }); + + }); + }); });