Skip to content

Commit

Permalink
Finish tests for preserveExtension file upload option
Browse files Browse the repository at this point in the history
  • Loading branch information
pronein committed Apr 30, 2017
1 parent 5bbf645 commit 85cfd3d
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 119 deletions.
19 changes: 11 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('.');
}
}
Expand Down
256 changes: 145 additions & 111 deletions test/options.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
}
});

0 comments on commit 85cfd3d

Please sign in to comment.