Merge pull request #150 from RomanBurunkov/master

Adds uriDecodeFileNames option
dev v1.1.5
Roman Burunkov 5 years ago committed by GitHub
commit f8116c49ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 21
      lib/index.js
  3. 9
      lib/processMultipart.js
  4. 12
      lib/utilities.js
  5. 2
      package.json
  6. 24
      test/utilities.spec.js

@ -76,6 +76,7 @@ Pass in non-Busboy options directly to the middleware. These are express-fileupl
Option | Acceptable Values | Details
--- | --- | ---
createParentPath | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Automatically creates the directory path specified in `.mv(filePathName)`
uriDecodeFileNames | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Applies uri decoding to file names if set true.
safeFileNames | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></li><li>regex</li></ul> | Strips characters from the upload's filename. You can use custom regex to determine what to strip. If set to `true`, non-alphanumeric characters _except_ dashes and underscores will be stripped. This option is off by default.<br /><br />**Example #1 (strip slashes from file names):** `app.use(fileUpload({ safeFileNames: /\\/g }))`<br />**Example #2:** `app.use(fileUpload({ safeFileNames: true }))`
preserveExtension | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></li><li><code>*Number*</code></li></ul> | Preserves filename extension when using <code>safeFileNames</code> option. If set to <code>true</code>, will default to an extension length of 3. If set to <code>*Number*</code>, this will be the max allowable extension length. If an extension is smaller than the extension length, it remains untouched. If the extension is longer, it is shifted.<br /><br />**Example #1 (true):**<br /><code>app.use(fileUpload({ safeFileNames: true, preserveExtension: true }));</code><br />*myFileName.ext* --> *myFileName.ext*<br /><br />**Example #2 (max extension length 2, extension shifted):**<br /><code>app.use(fileUpload({ safeFileNames: true, preserveExtension: 2 }));</code><br />*myFileName.ext* --> *myFileNamee.xt*
abortOnLimit | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Returns a HTTP 413 when the file is bigger than the size limit if true. Otherwise, it will add a <code>truncate = true</code> to the resulting file structure.

@ -1,12 +1,14 @@
'use strict';
const fileFactory = require('./fileFactory');
const processMultipart = require('./processMultipart');
const isEligibleRequest = require('./isEligibleRequest');
const processNested = require('./processNested');
const {buildOptions} = require('./utilities');
const processMultipart = require('./processMultipart');
const isEligibleRequest = require('./isEligibleRequest');
const fileUploadOptionsDefaults = {
const DEFAULT_OPTIONS = {
fileHandler: false,
uriDecodeFileNames: false,
safeFileNames: false,
preserveExtension: false,
abortOnLimit: false,
@ -20,15 +22,14 @@ const fileUploadOptionsDefaults = {
/**
* Expose the file upload middleware
* @param {Object} options - Middleware options.
* @returns {Function}
*/
module.exports = (fileUploadOptions) => {
fileUploadOptions = buildOptions(fileUploadOptionsDefaults, fileUploadOptions);
return function(req, res, next){
if (!isEligibleRequest(req)) {
return next();
}
module.exports = (options) => {
const fileUploadOptions = buildOptions(DEFAULT_OPTIONS, options);
return (req, res, next) => {
if (!isEligibleRequest(req)) return next();
processMultipart(fileUploadOptions, req, res, next);
};
};

@ -7,7 +7,8 @@ const {
isFunc,
buildOptions,
buildFields,
parseFileName
parseFileName,
uriDecodeFileName
} = require('./utilities');
/**
@ -31,8 +32,10 @@ module.exports = (options, req, res, next) => {
busboy.on('field', (fieldname, val) => req.body = buildFields(req.body, fieldname, val));
// Build req.files fields
busboy.on('file', (fieldname, file, filename, encoding, mime) => {
busboy.on('file', (fieldname, file, name, encoding, mime) => {
// Decode file name if uriDecodeFileNames option set true.
const filename = uriDecodeFileName(options, name);
const {dataHandler, getFilePath, getFileSize, getHash, complete, cleanup} = options.useTempFiles
? tempFileHandler(options, fieldname, filename)
: memHandler(options, fieldname, filename);

@ -182,6 +182,15 @@ const saveBufferToFile = (buffer, filePath, callback) => {
readStream.pipe(fstream);
};
/**
* Decodes uriEncoded file names.
* @param fileName {String} - file name to decode.
* @returns {String}
*/
const uriDecodeFileName = (opts, fileName) => {
return opts.uriDecodeFileNames ? decodeURIComponent(fileName) : fileName;
};
/**
* Parses filename and extension and returns object {name, extension}.
* @param preserveExtension {Boolean, Integer} - true/false or number of characters for extension.
@ -248,5 +257,6 @@ module.exports = {
moveFile,
saveBufferToFile,
parseFileName,
getTempFilename
getTempFilename,
uriDecodeFileName
};

@ -1,6 +1,6 @@
{
"name": "express-fileupload",
"version": "1.1.4",
"version": "1.1.5",
"author": "Richard Girges <richardgirges@gmail.com>",
"description": "Simple express file upload middleware that wraps around Busboy",
"main": "./lib/index",

@ -363,4 +363,28 @@ describe('Test of the utilities functions', function() {
});
});
});
describe('Test uriDecodeFileName function', function() {
const testData = [
{ enc: 'test%22filename', dec: 'test"filename' },
{ enc: 'test%60filename', dec: 'test`filename' },
{ enc: '%3Fx%3Dtest%22filename', dec: '?x=test"filename'}
];
// Test decoding if uriDecodeFileNames: true.
testData.forEach((testName) => {
const opts = { uriDecodeFileNames: true };
it(`Return ${testName.dec} for input ${testName.enc} if uriDecodeFileNames: true`, () => {
assert.equal(uriDecodeFileName(opts, testName.enc), testName.dec);
});
});
// Test decoding if uriDecodeFileNames: false.
testData.forEach((testName) => {
const opts = { uriDecodeFileNames: false };
it(`Return ${testName.enc} for input ${testName.enc} if uriDecodeFileNames: false`, () => {
assert.equal(uriDecodeFileName(opts, testName.enc), testName.enc);
});
});
});
});

Loading…
Cancel
Save