feat: check for real mimetype using file-type
For now, if file-type returns undefined, we take the value from the browser. In the future this should be removed to ensure people can't bypass the real mime checking using a special file that can't be recognized by file-type.
This commit is contained in:
parent
46ec3f7168
commit
53f5015c99
|
@ -2850,6 +2850,11 @@
|
|||
"@sinonjs/commons": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"@tokenizer/token": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz",
|
||||
"integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w=="
|
||||
},
|
||||
"@types/babel__core": {
|
||||
"version": "7.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
|
||||
|
@ -2901,6 +2906,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
|
||||
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
|
||||
},
|
||||
"@types/debug": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
|
||||
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ=="
|
||||
},
|
||||
"@types/graceful-fs": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz",
|
||||
|
@ -2942,8 +2952,7 @@
|
|||
"@types/node": {
|
||||
"version": "14.14.19",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.19.tgz",
|
||||
"integrity": "sha512-4nhBPStMK04rruRVtVc6cDqhu7S9GZai0fpXgPXrFpcPX6Xul8xnrjSdGB4KPBVYG/R5+fXWdCM8qBoiULWGPQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-4nhBPStMK04rruRVtVc6cDqhu7S9GZai0fpXgPXrFpcPX6Xul8xnrjSdGB4KPBVYG/R5+fXWdCM8qBoiULWGPQ=="
|
||||
},
|
||||
"@types/normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
|
@ -2962,6 +2971,15 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
||||
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
|
||||
},
|
||||
"@types/readable-stream": {
|
||||
"version": "2.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.9.tgz",
|
||||
"integrity": "sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==",
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"safe-buffer": "*"
|
||||
}
|
||||
},
|
||||
"@types/stack-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz",
|
||||
|
@ -7439,6 +7457,17 @@
|
|||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
|
||||
"integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
|
||||
},
|
||||
"file-type": {
|
||||
"version": "16.1.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-16.1.0.tgz",
|
||||
"integrity": "sha512-G4Klqf6tuprtG0pC4r9kni4Wv8XhAAsfHphVqsQGA+YiOlPAO40BZduDqKfv0RFsu9q9ZbFObWfwszY/NqhEZw==",
|
||||
"requires": {
|
||||
"readable-web-to-node-stream": "^3.0.0",
|
||||
"strtok3": "^6.0.3",
|
||||
"token-types": "^2.0.0",
|
||||
"typedarray-to-buffer": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
|
@ -13154,6 +13183,11 @@
|
|||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"peek-readable": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.1.tgz",
|
||||
"integrity": "sha512-QHJag0oYYPVkx6rVPEgCLEUMo6VRYbV3GUrqy00lxXJBEIw9LhPCP5MQI6mEfahJO9KYUP8W8qD8kC0V9RyZFQ=="
|
||||
},
|
||||
"pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
|
@ -14929,6 +14963,27 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"readable-web-to-node-stream": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.1.tgz",
|
||||
"integrity": "sha512-4zDC6CvjUyusN7V0QLsXVB7pJCD9+vtrM9bYDRv6uBQ+SKfx36rp5AFNPRgh9auKRul/a1iFZJYXcCbwRL+SaA==",
|
||||
"requires": {
|
||||
"@types/readable-stream": "^2.3.9",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
|
||||
|
@ -16359,6 +16414,16 @@
|
|||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
|
||||
},
|
||||
"strtok3": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.6.tgz",
|
||||
"integrity": "sha512-fVxvAEKDwHFfbQO1yKxKBPfkWZyBr0Zf20UQ/mblbkAQe5h0Xdd2jDb3Mh7yRZd7LSItJ9JWgQWelpEmVoBe2g==",
|
||||
"requires": {
|
||||
"@tokenizer/token": "^0.1.1",
|
||||
"@types/debug": "^4.1.5",
|
||||
"peek-readable": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"style-resources-loader": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/style-resources-loader/-/style-resources-loader-1.3.3.tgz",
|
||||
|
@ -16470,6 +16535,11 @@
|
|||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||
"dev": true
|
||||
},
|
||||
"systeminformation": {
|
||||
"version": "4.33.8",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.33.8.tgz",
|
||||
"integrity": "sha512-2kTDsCO/NBQArncwJ3ZA0qQOMTCdqixcggVxlPJrtinfQ42f3x4BAmIwmzkOlAsYYVnT63vOYHlunC2dNyZzTA=="
|
||||
},
|
||||
"table": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-6.0.6.tgz",
|
||||
|
@ -16913,6 +16983,15 @@
|
|||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"token-types": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/token-types/-/token-types-2.0.0.tgz",
|
||||
"integrity": "sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw==",
|
||||
"requires": {
|
||||
"@tokenizer/token": "^0.1.0",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"toposort": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
|
||||
|
@ -17057,7 +17136,6 @@
|
|||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"express-rate-limit": "^3.4.0",
|
||||
"ffmpeg-probe": "^1.0.6",
|
||||
"file-saver": "^2.0.1",
|
||||
"file-type": "^16.1.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"fs-jetpack": "^2.2.2",
|
||||
"helmet": "^3.15.1",
|
||||
|
@ -74,6 +75,7 @@
|
|||
"serve-static": "^1.13.2",
|
||||
"sharp": "^0.27.0",
|
||||
"sqlite3": "^5.0.0",
|
||||
"systeminformation": "^4.33.8",
|
||||
"uuid": "^3.3.2",
|
||||
"v-clipboard": "^2.2.1",
|
||||
"vue-axios": "^2.1.4",
|
||||
|
|
|
@ -28,6 +28,6 @@ exports.up = async knex => {
|
|||
table.unique(['fileId', 'tagId']);
|
||||
});
|
||||
};
|
||||
exports.down = async knex => {
|
||||
exports.down = async () => {
|
||||
// Nothing
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const path = require('path');
|
||||
const jetpack = require('fs-jetpack');
|
||||
const multer = require('multer');
|
||||
|
||||
const Util = require('../../utils/Util');
|
||||
const Route = require('../../structures/Route');
|
||||
const multerStorage = require('../../utils/multerStorage');
|
||||
|
@ -10,6 +11,22 @@ const chunkedUploadsTimeout = 1800000;
|
|||
const chunksDir = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'chunks');
|
||||
const uploadDir = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER);
|
||||
|
||||
|
||||
const cleanUpChunks = async (uuid, onTimeout) => {
|
||||
// Remove tmp file
|
||||
await jetpack.removeAsync(path.join(chunksData[uuid].root, chunksData[uuid].filename))
|
||||
.catch(error => {
|
||||
if (error.code !== 'ENOENT') console.error(error);
|
||||
});
|
||||
|
||||
// Remove UUID dir
|
||||
await jetpack.removeAsync(chunksData[uuid].root);
|
||||
|
||||
// Delete cached chunks data
|
||||
if (!onTimeout) chunksData[uuid].clearTimeout();
|
||||
delete chunksData[uuid];
|
||||
};
|
||||
|
||||
class ChunksData {
|
||||
constructor(uuid, root) {
|
||||
this.uuid = uuid;
|
||||
|
@ -134,7 +151,7 @@ const uploadFile = async (req, res) => {
|
|||
// If the uploaded file is a chunk then just say that it was a success
|
||||
const uuid = req.body.uuid;
|
||||
if (chunksData[uuid] !== undefined) {
|
||||
req.files.forEach(file => {
|
||||
req.files.forEach(() => {
|
||||
chunksData[uuid].chunks++;
|
||||
});
|
||||
res.json({ success: true });
|
||||
|
@ -149,7 +166,7 @@ const uploadFile = async (req, res) => {
|
|||
return infoMap[0];
|
||||
};
|
||||
|
||||
const finishChunks = async (req, res) => {
|
||||
const finishChunks = async req => {
|
||||
const check = file => typeof file.uuid !== 'string' ||
|
||||
!chunksData[file.uuid] ||
|
||||
chunksData[file.uuid].chunks < 2;
|
||||
|
@ -228,21 +245,6 @@ const finishChunks = async (req, res) => {
|
|||
}
|
||||
};
|
||||
|
||||
const cleanUpChunks = async (uuid, onTimeout) => {
|
||||
// Remove tmp file
|
||||
await jetpack.removeAsync(path.join(chunksData[uuid].root, chunksData[uuid].filename))
|
||||
.catch(error => {
|
||||
if (error.code !== 'ENOENT') console.error(error);
|
||||
});
|
||||
|
||||
// Remove UUID dir
|
||||
await jetpack.removeAsync(chunksData[uuid].root);
|
||||
|
||||
// Delete cached chunks data
|
||||
if (!onTimeout) chunksData[uuid].clearTimeout();
|
||||
delete chunksData[uuid];
|
||||
};
|
||||
|
||||
class uploadPOST extends Route {
|
||||
constructor() {
|
||||
super('/upload', 'post', {
|
||||
|
|
|
@ -35,6 +35,10 @@ class Util {
|
|||
return blockedExtensions.includes(extension);
|
||||
}
|
||||
|
||||
static getMimeFromType(fileTypeMimeObj) {
|
||||
return fileTypeMimeObj ? fileTypeMimeObj.mime : undefined;
|
||||
}
|
||||
|
||||
static constructFilePublicLink(file) {
|
||||
/*
|
||||
TODO: This wont work without a reverse proxy serving both
|
||||
|
@ -225,6 +229,7 @@ class Util {
|
|||
|
||||
static async storeFileToDb(req, res, user, file, db) {
|
||||
const dbFile = await db.table('files')
|
||||
// eslint-disable-next-line func-names
|
||||
.where(function() {
|
||||
if (user === undefined) {
|
||||
this.whereNull('userId');
|
||||
|
|
|
@ -8,7 +8,7 @@ function DiskStorage(opts) {
|
|||
|
||||
if (typeof opts.destination === 'string') {
|
||||
jetpack.dir(opts.destination);
|
||||
this.getDestination = function($0, $1, cb) { cb(null, opts.destination); };
|
||||
this.getDestination = ($0, $1, cb) => { cb(null, opts.destination); };
|
||||
} else {
|
||||
this.getDestination = opts.destination;
|
||||
}
|
||||
|
@ -86,6 +86,4 @@ DiskStorage.prototype._removeFile = function _removeFile(req, file, cb) {
|
|||
fs.unlink(path, cb);
|
||||
};
|
||||
|
||||
module.exports = function(opts) {
|
||||
return new DiskStorage(opts);
|
||||
};
|
||||
module.exports = opts => new DiskStorage(opts);
|
||||
|
|
Loading…
Reference in New Issue