Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 374: Allow an option to choose the hashing algorithm #375

Merged
merged 2 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ The **req.files.foo** object will contain the following:

* Before 1.0.0, `md5` is an MD5 checksum of the uploaded file.
* 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)).
* 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.
* 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.
* 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.


### Examples
Expand Down Expand Up @@ -124,6 +125,7 @@ parseNested | <ul><li><code>false</code>&nbsp;**(default)**</li><li><code>true</
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.
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.
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.
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.

# Help Wanted
Looking for additional maintainers. Please contact `richardgirges [ at ] gmail.com` if you're interested. Pull Requests are welcome!
Expand Down
3 changes: 2 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const DEFAULT_OPTIONS = {
createParentPath: false,
parseNested: false,
useTempFiles: false,
tempFileDir: path.join(process.cwd(), 'tmp')
tempFileDir: path.join(process.cwd(), 'tmp'),
hashAlgorithm: 'md5'
RomanBurunkov marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/memHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { debugLog } = require('./utilities');
*/
module.exports = (options, fieldname, filename) => {
const buffers = [];
const hash = crypto.createHash('md5');
const hash = crypto.createHash(options.hashAlgorithm);
let fileSize = 0;
let completed = false;

Expand Down
4 changes: 2 additions & 2 deletions lib/tempFileHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ module.exports = (options, fieldname, filename) => {
checkAndMakeDir({ createParentPath: true }, tempFilePath);

debugLog(options, `Temporary file path is ${tempFilePath}`);
const hash = crypto.createHash('md5');

const hash = crypto.createHash(options.hashAlgorithm);
let fileSize = 0;
let completed = false;

Expand Down
11 changes: 11 additions & 0 deletions lib/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const { Readable } = require('stream');

// Parameters for safe file name parsing.
Expand Down Expand Up @@ -68,13 +69,23 @@ const promiseCallback = (resolve, reject) => {
/**
* Builds instance options from arguments objects(can't be arrow function).
* @returns {Object} - result options.
* @throws {Error} - when a valid hashAlgorithm option is not provided.
*/
const buildOptions = function() {
const result = {};
[...arguments].forEach(options => {
if (!options || typeof options !== 'object') return;
Object.keys(options).forEach(i => result[i] = options[i]);
});

// Ensure the configured hashAlgorithm is available on the system
if (crypto.getHashes().find(h => result.hashAlgorithm === h) === undefined) {
throw Error(
`Hashing algorithm '${result.hashAlgorithm}' is not supported by this system's OpenSSL `
+ `version`
);
}

return result;
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "express-fileupload",
"version": "1.5.0",
"version": "1.5.1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new option is a feature — it should have been minor release (1.6.0)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @RobinTail

Partially agree with u.
In this case decided not to change 5 to 6, since change quite small and 100% backward compatible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it was incompatible, then it would be 2.0.0

https://semver.org

FYI

"author": "Richard Girges <[email protected]>",
"description": "Simple express file upload middleware that wraps around Busboy",
"main": "./lib/index",
Expand Down
19 changes: 13 additions & 6 deletions test/utilities.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ describe('utilities: Test of the utilities functions', function() {
//buildOptions tests
describe('Test buildOptions function', () => {

const source = { option1: '1', option2: '2' };
const sourceAddon = { option3: '3'};
const expected = { option1: '1', option2: '2' };
const expectedAddon = { option1: '1', option2: '2', option3: '3'};
const source = { option1: '1', option2: '2', hashAlgorithm: 'md5' };
const sourceAddon = { option3: '3', hashAlgorithm: 'sha256'};
const expected = { option1: '1', option2: '2', hashAlgorithm: 'md5' };
const expectedAddon = { option1: '1', option2: '2', option3: '3', hashAlgorithm: 'sha256'};

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

it('buildOptions adds value to the result from the several source argumets', () => {
it('buildOptions adds value to the result from the several source arguments', () => {
let result = buildOptions(source, sourceAddon);
assert.deepStrictEqual(result, expectedAddon);
});

it('buildOptions throws an error when not provided a supported hashAlgorithm', () => {
assert.throws(() => buildOptions({}));
});

it('buildOptions throws an error when given an unsupported hashAlgorithm', () => {
assert.throws(() => buildOptions({ hashAlgorithm: 'not-actual-algo' }));
});
});
//buildFields tests
describe('Test buildFields function', () => {
Expand Down