@ -2,7 +2,6 @@
const fs = require ( 'fs' ) ;
const path = require ( 'path' ) ;
const mkdirp = require ( 'mkdirp' ) ;
const Readable = require ( 'stream' ) . Readable ;
// Parameters for safe file name parsing.
@ -55,7 +54,15 @@ const errorFunc = (resolve, reject) => isFunc(reject) ? reject : resolve;
* @ returns { Function }
* /
const promiseCallback = ( resolve , reject ) => {
return err => err ? errorFunc ( resolve , reject ) ( err ) : resolve ( ) ;
let hasFired = false ;
return ( err ) => {
if ( hasFired ) {
return ;
}
hasFired = true ;
return err ? errorFunc ( resolve , reject ) ( err ) : resolve ( ) ;
} ;
} ;
/ * *
@ -71,6 +78,26 @@ const buildOptions = function(){
return result ;
} ;
// The default prototypes for both objects and arrays.
// Used by isSafeFromPollution
const OBJECT _PROTOTYPE _KEYS = Object . getOwnPropertyNames ( Object . prototype ) ;
const ARRAY _PROTOTYPE _KEYS = Object . getOwnPropertyNames ( Array . prototype ) ;
/ * *
* Determines whether a key insertion into an object could result in a prototype pollution
* @ param { Object } base - The object whose insertion we are checking
* @ param { string } key - The key that will be inserted
* /
const isSafeFromPollution = ( base , key ) => {
// We perform an instanceof check instead of Array.isArray as the former is more
// permissive for cases in which the object as an Array prototype but was not constructed
// via an Array constructor or literal.
const TOUCHES _ARRAY _PROTOTYPE = ( base instanceof Array ) && ARRAY _PROTOTYPE _KEYS . includes ( key ) ;
const TOUCHES _OBJECT _PROTOTYPE = OBJECT _PROTOTYPE _KEYS . includes ( key ) ;
return ! TOUCHES _ARRAY _PROTOTYPE && ! TOUCHES _OBJECT _PROTOTYPE ;
} ;
/ * *
* Builds request fields ( using to build req . body and req . files )
* @ param { Object } instance - request object .
@ -81,7 +108,11 @@ const buildOptions = function(){
const buildFields = ( instance , field , value ) => {
// Do nothing if value is not set.
if ( value === null || value === undefined ) return instance ;
instance = instance || { } ;
instance = instance || Object . create ( null ) ;
if ( ! isSafeFromPollution ( instance , field ) ) {
return instance ;
}
// Non-array fields
if ( ! instance [ field ] ) {
instance [ field ] = value ;
@ -110,18 +141,17 @@ const checkAndMakeDir = (fileUploadOptions, filePath) => {
if ( ! filePath ) return false ;
const parentPath = path . dirname ( filePath ) ;
// Create folder if it does not exist.
if ( ! fs . existsSync ( parentPath ) ) {
mkdirp . sync ( parentPath ) ;
}
if ( ! fs . existsSync ( parentPath ) ) fs . mkdirSync ( parentPath , { recursive : true } ) ;
// Check folder again and return the result.
return fs . existsSync ( parentPath ) ;
} ;
/ * *
* Delete file .
* @ param { String } file - Path to the file to delete .
* Deletes a file .
* @ param { string } file - Path to the file to delete .
* @ param { Function } callback
* /
const deleteFile = ( file , callback ) => fs . unlink ( file , err => err ? callback ( err ) : callback ( ) ) ;
const deleteFile = ( file , callback ) => fs . unlink ( file , callback ) ;
/ * *
* Copy file via streams
@ -151,15 +181,15 @@ const copyFile = (src, dst, callback) => {
} ;
/ * *
* moveFile - moves the file from src to dst .
* moveFile : moves the file from src to dst .
* Firstly trying to rename the file if no luck copying it to dst and then deleteing src .
* @ param { S tring} src - Path to the source file
* @ param { S tring} dst - Path to the destination file .
* @ param { s tring} src - Path to the source file
* @ param { s tring} dst - Path to the destination file .
* @ param { Function } callback - A callback function .
* /
const moveFile = ( src , dst , callback ) => fs . rename ( src , dst , err => ( ! err
? callback ( )
: copyFile ( src , dst , err => err ? c allback ( err ) : deleteFile ( src , callback ) )
const moveFile = ( src , dst , callback ) => fs . rename ( src , dst , err => ( err
? copyFile ( src , dst , err => err ? c allback ( err ) : deleteFile ( src , callback ) )
: callback ( )
) ) ;
/ * *
@ -275,5 +305,6 @@ module.exports = {
saveBufferToFile ,
parseFileName ,
getTempFilename ,
uriDecodeFileName
uriDecodeFileName ,
isSafeFromPollution ,
} ;