From 85cfd3d19808f7ca2ae0601c7c257694d9d5eb8d Mon Sep 17 00:00:00 2001 From: Adam Schrader Date: Sat, 29 Apr 2017 21:24:25 -0400 Subject: [PATCH] Finish tests for preserveExtension file upload option --- lib/index.js | 19 ++-- test/options.spec.js | 256 ++++++++++++++++++++++++------------------- 2 files changed, 156 insertions(+), 119 deletions(-) diff --git a/lib/index.js b/lib/index.js index 885025f..851a8f4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -89,28 +89,31 @@ function processMultipart(options, req, res, next) { return; if (options.safeFileNames) { - let extensionLength = 3; + let maxExtensionLength = 3; let extension = ''; if (typeof options.safeFileNames === 'object') safeFileNameRegex = options.safeFileNames; - if (options.preserveExtension) { - if (typeof options.preserveExtension === 'number') - extensionLength = options.preserveExtension; + maxExtensionLength = parseInt(options.preserveExtension); + if (options.preserveExtension || maxExtensionLength === 0) { + if (isNaN(maxExtensionLength)) + maxExtensionLength = 3; + else + maxExtensionLength = Math.abs(maxExtensionLength); let filenameParts = filename.split('.'); let filenamePartsLen = filenameParts.length; if (filenamePartsLen > 1) { extension = filenameParts.pop(); - if (extension.length > extensionLength) { + if (extension.length > maxExtensionLength && maxExtensionLength > 0) { filenameParts[filenameParts.length - 1] += - '.' + extension.substr(0, extension.length - extensionLength); - extension = extension.substr(-extensionLength); + '.' + extension.substr(0, extension.length - maxExtensionLength); + extension = extension.substr(-maxExtensionLength); } - extension = '.' + extension.replace(safeFileNameRegex, ''); + extension = maxExtensionLength ? '.' + extension.replace(safeFileNameRegex, '') : ''; filename = filenameParts.join('.'); } } diff --git a/test/options.spec.js b/test/options.spec.js index 32e49c5..d532c02 100644 --- a/test/options.spec.js +++ b/test/options.spec.js @@ -2,150 +2,184 @@ const fs = require('fs'); const path = require('path'); const request = require('supertest'); const server = require('./server'); -// const clearUploadsDir = server.clearUploadsDir; +const clearUploadsDir = server.clearUploadsDir; const fileDir = server.fileDir; const uploadDir = server.uploadDir; -describe('SafeFileNames', function() { - it(`Does nothing to your filename when disabled.`, function(done) { - const app = server.setup({safeFileNames: false}); +describe('File Upload Options Tests', function() { + afterEach(function(done) { + clearUploadsDir(); + done(); + }); - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'my$Invalid#fileName.png123')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); + describe('Testing [safeFileNames] option to ensure:', function() { + it('Does nothing to your filename when disabled.', + function(done) { + const fileUploadOptions = {safeFileNames: false}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'my$Invalid#fileName.png123'; - let uploadedFilePath = path.join(uploadDir, 'my$Invalid#fileName.png123'); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); - fs.stat(uploadedFilePath, done); + it('Is disabled by default.', + function(done) { + const fileUploadOptions = null; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'my$Invalid#fileName.png123'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); }); - }); - it(`Strips away all illegal characters (including spaces) when enabled.`, function(done) { - const app = server.setup({safeFileNames: true}); + it('Strips away all non-alphanumeric characters (excluding hyphens/underscores) when enabled.', + function(done) { + const fileUploadOptions = {safeFileNames: true}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng123'; - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'my$Invalid#fileName.png123')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); - let uploadedFilePath = path.join(uploadDir, 'myInvalidfileNamepng123'); + it('Accepts a regex for stripping (decidedly) "invalid" characters from filename.', + function(done) { + const fileUploadOptions = {safeFileNames: /[\$#]/g}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileName.png123'; - fs.stat(uploadedFilePath, done); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); }); }); - it(`Respects a regex for stripping 'invalid' characters from filename.`, function(done) { - const app = server.setup({safeFileNames: /[\$#]/g}); + describe('Testing [preserveExtension] option to ensure:', function() { + it('Does not preserve the extension of your filename when disabled.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: false}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng123'; - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'my$Invalid#fileName.png123')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); - let uploadedFilePath = path.join(uploadDir, 'myInvalidfileName.png123'); + it('Is disabled by default.', + function(done) { + const fileUploadOptions = {safeFileNames: true}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng123'; - fs.stat(uploadedFilePath, done); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); }); - }); -}); -describe(`preserveExtension`, function() { - it(`Does nothing to your filename when disabled.`, function(done) { - const app = server.setup({safeFileNames: true, preserveExtension: false}); + it('Shortens your extension to the default(3) when enabled, if the extension found is larger.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: true}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng.123'; - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'my$Invalid#fileName.png123')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); - let uploadedFilePath = path.join(uploadDir, 'myInvalidfileNamepng123'); + it('Leaves your extension alone when enabled, if the extension found is <= default(3) length', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: true}; + const actualFileName = 'car.png'; + const expectedFileName = 'car.png'; - fs.stat(uploadedFilePath, done); + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Can be configured for an extension length > default(3).', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: 7}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileName.png123'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Can be configured for an extension length < default(3).', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: 2}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng1.23'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Will use the absolute value of your extension length when negative.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: -5}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamep.ng123'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Will leave no extension when the extension length == 0.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: 0}; + const actualFileName = 'car.png'; + const expectedFileName = 'car'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Will accept numbers as strings, if they can be resolved with parseInt.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: '3'}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng.123'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Will be evaluated for truthy-ness if it cannot be parsed as an int.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: 'not-a-#-but-truthy'}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepng.123'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Will ignore any decimal amount when evaluating for extension length.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: 4.98}; + const actualFileName = 'my$Invalid#fileName.png123'; + const expectedFileName = 'myInvalidfileNamepn.g123'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); + }); + + it('Only considers the last dotted part as the extension.', + function(done) { + const fileUploadOptions = {safeFileNames: true, preserveExtension: true}; + const actualFileName = 'basket.ball.bp'; + const expectedFileName = 'basketball.bp'; + + executeFileUploadTestWalk(fileUploadOptions, actualFileName, expectedFileName, done); }); }); - it(`Shortens your extension to the default(3) when enabled, if the extension found is larger`, - function(done) { - const app = server.setup({safeFileNames: true, preserveExtension: true}); + function executeFileUploadTestWalk(options, + actualFileNameToUpload, + expectedFilNameOnFileSystem, + done) { + const argsUnderTest = options; + const app = server.setup(argsUnderTest); + const actualFileName = actualFileNameToUpload; + const expectedFileName = expectedFilNameOnFileSystem; request(app) .post('/upload/single') - .attach('testFile', path.join(fileDir, 'my$Invalid#fileName.png123')) + .attach('testFile', path.join(fileDir, actualFileName)) .expect(200) - .end(function(err, res) { + .end(function(err) { if (err) return done(err); - let uploadedFilePath = path.join(uploadDir, 'myInvalidfileNamepng.123'); + const uploadedFilePath = path.join(uploadDir, expectedFileName); fs.stat(uploadedFilePath, done); }); - }); - - it(`Leaves your extension alone when enabled, if the extension found is <= default(3) length`, - function(done) { - const app = server.setup({safeFileNames: true, preserveExtension: true}); - - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'car.png')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); - - let uploadedFilePath = path.join(uploadDir, 'car.png'); - - fs.stat(uploadedFilePath, done); - }); - }); - - it(`Leaves your extension alone when set to a number >= the extension length.`, - function(done) { - const app = server.setup({safeFileNames: true, preserveExtension: 7}); - - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'my$Invalid#fileName.png123')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); - - let uploadedFilePath = path.join(uploadDir, 'myInvalidfileName.png123'); - - fs.stat(uploadedFilePath, done); - }); - }); - - it(`Only considers the last dotted part the extension.`, - function(done) { - const app = server.setup({safeFileNames: true, preserveExtension: true}); - - request(app) - .post('/upload/single') - .attach('testFile', path.join(fileDir, 'basket.ball.bp')) - .expect(200) - .end(function(err, res) { - if (err) - return done(err); - - let uploadedFilePath = path.join(uploadDir, 'basketball.bp'); - - fs.stat(uploadedFilePath, done); - }); - }); + } });