mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2024-12-13 16:06:21 +00:00
86c26cb50c
only usergroup and file extension bypass real file size can't be determined before passthrough scan, so there's no bypass by max file size please read the comments in sample config file refactored utils.clamscan into utils.scan
128 lines
3.4 KiB
JavaScript
128 lines
3.4 KiB
JavaScript
const fs = require('fs')
|
|
const path = require('path')
|
|
const blake3 = require('blake3')
|
|
const mkdirp = require('mkdirp')
|
|
const logger = require('./../../logger')
|
|
|
|
const REQUIRED_WEIGHT = 2
|
|
|
|
function DiskStorage (opts) {
|
|
this.getFilename = opts.filename
|
|
|
|
if (typeof opts.destination === 'string') {
|
|
mkdirp.sync(opts.destination)
|
|
this.getDestination = function ($0, $1, cb) { cb(null, opts.destination) }
|
|
} else {
|
|
this.getDestination = opts.destination
|
|
}
|
|
|
|
this.scan = opts.scan
|
|
this.scanHelpers = opts.scanHelpers
|
|
}
|
|
|
|
DiskStorage.prototype._handleFile = function _handleFile (req, file, cb) {
|
|
const that = this
|
|
|
|
// "weighted" callback, to be able to "await" multiple callbacks
|
|
let tempError = null
|
|
let tempObject = {}
|
|
let tempWeight = 0
|
|
const _cb = (err = null, result = {}, weight = 2) => {
|
|
tempError = err
|
|
tempWeight += weight
|
|
tempObject = Object.assign(result, tempObject)
|
|
if (tempError || tempWeight >= REQUIRED_WEIGHT) {
|
|
cb(tempError, tempObject)
|
|
}
|
|
}
|
|
|
|
that.getDestination(req, file, function (err, destination) {
|
|
if (err) return _cb(err)
|
|
|
|
that.getFilename(req, file, function (err, filename) {
|
|
if (err) return _cb(err)
|
|
|
|
const finalPath = path.join(destination, filename)
|
|
const onerror = err => {
|
|
hash.dispose()
|
|
_cb(err)
|
|
}
|
|
|
|
let outStream
|
|
let hash
|
|
let scanStream
|
|
if (file._isChunk) {
|
|
if (!file._chunksData.stream) {
|
|
file._chunksData.stream = fs.createWriteStream(finalPath, { flags: 'a' })
|
|
file._chunksData.stream.on('error', onerror)
|
|
}
|
|
if (!file._chunksData.hasher) {
|
|
file._chunksData.hasher = blake3.createHash()
|
|
}
|
|
|
|
outStream = file._chunksData.stream
|
|
hash = file._chunksData.hasher
|
|
} else {
|
|
outStream = fs.createWriteStream(finalPath)
|
|
outStream.on('error', onerror)
|
|
hash = blake3.createHash()
|
|
|
|
if (that.scan.passthrough &&
|
|
!that.scanHelpers.assertUserBypass(req._user, filename) &&
|
|
!that.scanHelpers.assertFileBypass({ filename })) {
|
|
scanStream = that.scan.instance.passthrough()
|
|
}
|
|
}
|
|
|
|
file.stream.on('error', onerror)
|
|
file.stream.on('data', d => hash.update(d))
|
|
|
|
if (file._isChunk) {
|
|
file.stream.on('end', () => {
|
|
_cb(null, {
|
|
destination,
|
|
filename,
|
|
path: finalPath
|
|
})
|
|
})
|
|
file.stream.pipe(outStream, { end: false })
|
|
} else {
|
|
outStream.on('finish', () => {
|
|
_cb(null, {
|
|
destination,
|
|
filename,
|
|
path: finalPath,
|
|
size: outStream.bytesWritten,
|
|
hash: hash.digest('hex')
|
|
}, scanStream ? 1 : 2)
|
|
})
|
|
|
|
if (scanStream) {
|
|
logger.debug(`[ClamAV]: ${filename}: Passthrough scanning\u2026`)
|
|
scanStream.on('error', onerror)
|
|
scanStream.on('scan-complete', scan => {
|
|
_cb(null, { scan }, 1)
|
|
})
|
|
file.stream.pipe(scanStream).pipe(outStream)
|
|
} else {
|
|
file.stream.pipe(outStream)
|
|
}
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
DiskStorage.prototype._removeFile = function _removeFile (req, file, cb) {
|
|
const path = file.path
|
|
|
|
delete file.destination
|
|
delete file.filename
|
|
delete file.path
|
|
|
|
fs.unlink(path, cb)
|
|
}
|
|
|
|
module.exports = function (opts) {
|
|
return new DiskStorage(opts)
|
|
}
|