Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

express-fileupload

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-fileupload - npm Package Compare versions

Comparing version 1.1.4 to 1.1.5

21

lib/index.js
'use strict';
const fileFactory = require('./fileFactory');
const processNested = require('./processNested');
const {buildOptions} = require('./utilities');
const processMultipart = require('./processMultipart');
const isEligibleRequest = require('./isEligibleRequest');
const processNested = require('./processNested');
const {buildOptions} = require('./utilities');
const fileUploadOptionsDefaults = {
const DEFAULT_OPTIONS = {
fileHandler: false,
uriDecodeFileNames: false,
safeFileNames: false,

@@ -23,11 +25,10 @@ preserveExtension: false,

* Expose the file upload middleware
* @param {Object} options - Middleware options.
* @returns {Function}
*/
module.exports = (fileUploadOptions) => {
fileUploadOptions = buildOptions(fileUploadOptionsDefaults, fileUploadOptions);
module.exports = (options) => {
const fileUploadOptions = buildOptions(DEFAULT_OPTIONS, options);
return function(req, res, next){
if (!isEligibleRequest(req)) {
return next();
}
return (req, res, next) => {
if (!isEligibleRequest(req)) return next();
processMultipart(fileUploadOptions, req, res, next);

@@ -34,0 +35,0 @@ };

@@ -16,3 +16,3 @@ const crypto = require('crypto');

const getBuffer = () => Buffer.concat(buffers);
const getBuffer = () => Buffer.concat(buffers, fileSize);
const emptyFunc = () => '';

@@ -19,0 +19,0 @@

@@ -10,3 +10,4 @@ const Busboy = require('busboy');

buildFields,
parseFileName
parseFileName,
uriDecodeFileName
} = require('./utilities');

@@ -35,4 +36,6 @@

// 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

@@ -39,0 +42,0 @@ ? tempFileHandler(options, fieldname, filename)

@@ -36,4 +36,3 @@ 'use strict';

prefix = prefix || TEMP_PREFIX;
tempCounter ++;
if (tempCounter > TEMP_COUNTER_MAX) tempCounter = 1;
tempCounter = tempCounter >= TEMP_COUNTER_MAX ? 1 : tempCounter + 1;
return `${prefix}-${tempCounter}-${Date.now()}`;

@@ -59,17 +58,11 @@ };

const promiseCallback = (resolve, reject) => {
return (err) => {
if (err) {
errorFunc(resolve, reject)(err);
} else {
resolve();
}
};
return err => err ? errorFunc(resolve, reject)(err) : resolve();
};
/**
* Builds instance options from arguments objects.
* Builds instance options from arguments objects(can't be arrow function).
* @returns {Object} - result options.
*/
const buildOptions = function(){
let result = {};
const result = {};
[...arguments].forEach(options => {

@@ -90,6 +83,4 @@ if (!options || typeof options !== 'object') return;

const buildFields = (instance, field, value) => {
//Do nothing if value is not set.
if (value === null || value === undefined){
return instance;
}
// Do nothing if value is not set.
if (value === null || value === undefined) return instance;
instance = instance || {};

@@ -101,3 +92,3 @@ // Non-array fields

// Array fields
if (instance[field] instanceof Array){
if (instance[field] instanceof Array) {
instance[field].push(value);

@@ -115,13 +106,15 @@ } else {

* @param {String} filePath
* @returns {Boolean}
*/
const checkAndMakeDir = function(fileUploadOptions, filePath){
//Check upload options were set.
const checkAndMakeDir = (fileUploadOptions, filePath) => {
// Check upload options were set.
if (!fileUploadOptions) return false;
if (!fileUploadOptions.createParentPath) return false;
//Check whether folder for the file exists.
// Check whether folder for the file exists.
if (!filePath) return false;
const parentPath = path.dirname(filePath);
//Create folder if it is not exists.
if (!fs.existsSync(parentPath)) fs.mkdirSync(parentPath);
return true;
// Create folder if it is not exists.
if (!fs.existsSync(parentPath)) fs.mkdirSync(parentPath, { recursive: true });
// Checks folder again and return a results.
return fs.existsSync(parentPath);
};

@@ -133,11 +126,3 @@

*/
const deleteFile = (file, callback) => {
fs.unlink(file, (err) => {
if (err) {
callback(err);
return;
}
callback();
});
};
const deleteFile = (file, callback) => fs.unlink(file, err => err ? callback(err) : callback());

@@ -149,4 +134,4 @@ /**

*/
const copyFile = function(src, dst, callback){
//cbCalled flag and runCb helps to run cb only once.
const copyFile = (src, dst, callback) => {
// cbCalled flag and runCb helps to run cb only once.
let cbCalled = false;

@@ -158,6 +143,6 @@ let runCb = (err) => {

};
//Create read stream
// Create read stream
let readable = fs.createReadStream(src);
readable.on('error', runCb);
//Create write stream
// Create write stream
let writable = fs.createWriteStream(dst);

@@ -169,3 +154,3 @@ writable.on('error', (err)=>{

writable.on('close', () => runCb());
//Copy file via piping streams.
// Copy file via piping streams.
readable.pipe(writable);

@@ -181,11 +166,4 @@ };

const moveFile = (src, dst, callback) => {
// Copy file to dst.
copyFile(src, dst, (err) => {
if (err) {
callback(err);
return;
}
// Delete src file.
deleteFile(src, callback);
});
// Copy file to dst and delete src whether success.
copyFile(src, dst, err => err ? callback(err) : deleteFile(src, callback));
};

@@ -198,19 +176,18 @@

*/
const saveBufferToFile = function(buffer, filePath, callback){
if (!Buffer.isBuffer(buffer)){
callback(new Error('buffer variable should be a Buffer!'));
return;
const saveBufferToFile = (buffer, filePath, callback) => {
if (!Buffer.isBuffer(buffer)) {
return callback(new Error('buffer variable should be type of Buffer!'));
}
//Setup readable stream from buffer.
// Setup readable stream from buffer.
let streamData = buffer;
let readStream = Readable();
readStream._read = ()=>{
readStream._read = () => {
readStream.push(streamData);
streamData = null;
};
//Setup file system writable stream.
// Setup file system writable stream.
let fstream = fs.createWriteStream(filePath);
fstream.on('error', error => callback(error));
fstream.on('close', () => callback());
//Copy file via piping streams.
// Copy file via piping streams.
readStream.pipe(fstream);

@@ -220,2 +197,11 @@ };

/**
* 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}.

@@ -227,16 +213,12 @@ * @param preserveExtension {Boolean, Integer} - true/false or number of characters for extension.

const parseFileNameExtension = (preserveExtension, fileName) => {
let preserveExtensionLengh = parseInt(preserveExtension);
let result = {name: fileName, extension: ''};
if (!preserveExtension && preserveExtensionLengh !== 0){
return result;
}
const preserveExtensionLengh = parseInt(preserveExtension);
const result = {name: fileName, extension: ''};
if (!preserveExtension && preserveExtensionLengh !== 0) return result;
// Define maximum extension length
let maxExtLength = isNaN(preserveExtensionLengh)
const maxExtLength = isNaN(preserveExtensionLengh)
? MAX_EXTENSION_LENGTH
: Math.abs(preserveExtensionLengh);
let nameParts = fileName.split('.');
if (nameParts.length < 2) {
return result;
}
const nameParts = fileName.split('.');
if (nameParts.length < 2) return result;

@@ -266,7 +248,5 @@ let extension = nameParts.pop();

const parseFileName = (opts, fileName) => {
if (!opts.safeFileNames) {
return fileName;
}
if (!opts.safeFileNames) return fileName;
// Set regular expression for the file name.
let safeNameRegex = typeof opts.safeFileNames === 'object' && opts.safeFileNames instanceof RegExp
const nameRegex = typeof opts.safeFileNames === 'object' && opts.safeFileNames instanceof RegExp
? opts.safeFileNames

@@ -276,5 +256,5 @@ : SAFE_FILE_NAME_REGEX;

let {name, extension} = parseFileNameExtension(opts.preserveExtension, fileName);
if (extension.length) extension = '.' + extension.replace(safeNameRegex, '');
if (extension.length) extension = '.' + extension.replace(nameRegex, '');
return name.replace(safeNameRegex, '').concat(extension);
return name.replace(nameRegex, '').concat(extension);
};

@@ -295,3 +275,4 @@

parseFileName,
getTempFilename
getTempFilename,
uriDecodeFileName
};
{
"name": "express-fileupload",
"version": "1.1.4",
"version": "1.1.5",
"author": "Richard Girges <richardgirges@gmail.com>",

@@ -5,0 +5,0 @@ "description": "Simple express file upload middleware that wraps around Busboy",

@@ -79,2 +79,3 @@ # express-fileupload

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 }))`

@@ -81,0 +82,0 @@ 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*

@@ -229,2 +229,7 @@ 'use strict';

});
//
it('checkAndMakeDir creates a dir recursively if path to the file not exists', ()=>{
let dir = path.join(uploadDir, 'testfolder', 'testsubfolder', 'testfile');
assert.equal(checkAndMakeDir({createParentPath: true}, dir), true);
});
});

@@ -362,2 +367,26 @@ //saveBufferToFile tests

});
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);
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc