Skip to content

Commit 2bc6274

Browse files
Merge pull request #375 from Kpovoc/master
Issue 374: Allow an option to choose the hashing algorithm
2 parents 3325e62 + 7349650 commit 2bc6274

File tree

7 files changed

+33
-12
lines changed

7 files changed

+33
-12
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ The **req.files.foo** object will contain the following:
5050

5151
* Before 1.0.0, `md5` is an MD5 checksum of the uploaded file.
5252
* From 1.0.0 until 1.1.1, `md5` is a function to compute an MD5 hash ([Read about it here.](https://github.com/richardgirges/express-fileupload/releases/tag/v1.0.0-alpha.1)).
53-
* From 1.1.1 onward, `md5` is reverted back to MD5 checksum value and also added full MD5 support in case you are using temporary files.
53+
* From 1.1.1 until 1.5.1, `md5` is reverted back to MD5 checksum value and also added full MD5 support in case you are using temporary files.
54+
* From 1.5.1 onward, `md5` still holds the checksum value, but the checksum is generated with the provided `hashAlgorithm` option. The property name remains `md5` for backwards compatibility.
5455

5556

5657
### Examples
@@ -124,6 +125,7 @@ parseNested | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</
124125
debug | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</code></ul> | Turn on/off upload process logging. Can be useful for troubleshooting.
125126
logger | <ul><li><code>console</code>&nbsp;**(default)**</li><li><code>{log: function(msg: string)}</code></li></ul> | Customizable logger to write debug messages to. Console is default.
126127
uploadTimeout | <ul><li><code>60000</code>&nbsp;**(default)**</li><li><code>Integer</code></ul> | This defines how long to wait for data before aborting. Set to 0 if you want to turn off timeout checks.
128+
hashAlgorithm | <ul><li><code>md5</code>&nbsp;**(default)**</li><li><code>String</code></li></ul> | Allows the usage of alternative hashing algorithms for file integrity checks. This option must be an algorithm that is supported on the running system's installed OpenSSL version. On recent releases of OpenSSL, <code>openssl list -digest-algorithms</code> will display the available digest algorithms.
127129

128130
# Help Wanted
129131
Looking for additional maintainers. Please contact `richardgirges [ at ] gmail.com` if you're interested. Pull Requests are welcome!

lib/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const DEFAULT_OPTIONS = {
2020
createParentPath: false,
2121
parseNested: false,
2222
useTempFiles: false,
23-
tempFileDir: path.join(process.cwd(), 'tmp')
23+
tempFileDir: path.join(process.cwd(), 'tmp'),
24+
hashAlgorithm: 'md5'
2425
};
2526

2627
/**

lib/memHandler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const { debugLog } = require('./utilities');
1010
*/
1111
module.exports = (options, fieldname, filename) => {
1212
const buffers = [];
13-
const hash = crypto.createHash('md5');
13+
const hash = crypto.createHash(options.hashAlgorithm);
1414
let fileSize = 0;
1515
let completed = false;
1616

lib/tempFileHandler.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ module.exports = (options, fieldname, filename) => {
1414
checkAndMakeDir({ createParentPath: true }, tempFilePath);
1515

1616
debugLog(options, `Temporary file path is ${tempFilePath}`);
17-
18-
const hash = crypto.createHash('md5');
17+
18+
const hash = crypto.createHash(options.hashAlgorithm);
1919
let fileSize = 0;
2020
let completed = false;
2121

lib/utilities.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const fs = require('fs');
44
const path = require('path');
5+
const crypto = require('crypto');
56
const { Readable } = require('stream');
67

78
// Parameters for safe file name parsing.
@@ -68,13 +69,23 @@ const promiseCallback = (resolve, reject) => {
6869
/**
6970
* Builds instance options from arguments objects(can't be arrow function).
7071
* @returns {Object} - result options.
72+
* @throws {Error} - when a valid hashAlgorithm option is not provided.
7173
*/
7274
const buildOptions = function() {
7375
const result = {};
7476
[...arguments].forEach(options => {
7577
if (!options || typeof options !== 'object') return;
7678
Object.keys(options).forEach(i => result[i] = options[i]);
7779
});
80+
81+
// Ensure the configured hashAlgorithm is available on the system
82+
if (crypto.getHashes().find(h => result.hashAlgorithm === h) === undefined) {
83+
throw Error(
84+
`Hashing algorithm '${result.hashAlgorithm}' is not supported by this system's OpenSSL `
85+
+ `version`
86+
);
87+
}
88+
7889
return result;
7990
};
8091

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "express-fileupload",
3-
"version": "1.5.0",
3+
"version": "1.5.1",
44
"author": "Richard Girges <[email protected]>",
55
"description": "Simple express file upload middleware that wraps around Busboy",
66
"main": "./lib/index",

test/utilities.spec.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,12 @@ describe('utilities: Test of the utilities functions', function() {
198198
//buildOptions tests
199199
describe('Test buildOptions function', () => {
200200

201-
const source = { option1: '1', option2: '2' };
202-
const sourceAddon = { option3: '3'};
203-
const expected = { option1: '1', option2: '2' };
204-
const expectedAddon = { option1: '1', option2: '2', option3: '3'};
201+
const source = { option1: '1', option2: '2', hashAlgorithm: 'md5' };
202+
const sourceAddon = { option3: '3', hashAlgorithm: 'sha256'};
203+
const expected = { option1: '1', option2: '2', hashAlgorithm: 'md5' };
204+
const expectedAddon = { option1: '1', option2: '2', option3: '3', hashAlgorithm: 'sha256'};
205205

206-
it('buildOptions returns and equal object to the object which was paased', () => {
206+
it('buildOptions returns an equal object to the object which was passed', () => {
207207
let result = buildOptions(source);
208208
assert.deepStrictEqual(result, source);
209209
});
@@ -213,11 +213,18 @@ describe('utilities: Test of the utilities functions', function() {
213213
assert.deepStrictEqual(result, expected);
214214
});
215215

216-
it('buildOptions adds value to the result from the several source argumets', () => {
216+
it('buildOptions adds value to the result from the several source arguments', () => {
217217
let result = buildOptions(source, sourceAddon);
218218
assert.deepStrictEqual(result, expectedAddon);
219219
});
220220

221+
it('buildOptions throws an error when not provided a supported hashAlgorithm', () => {
222+
assert.throws(() => buildOptions({}));
223+
});
224+
225+
it('buildOptions throws an error when given an unsupported hashAlgorithm', () => {
226+
assert.throws(() => buildOptions({ hashAlgorithm: 'not-actual-algo' }));
227+
});
221228
});
222229
//buildFields tests
223230
describe('Test buildFields function', () => {

0 commit comments

Comments
 (0)