Merge branch 'dev' into 'master'

Miroku++ : Critical Fixes

See merge request Shinobi-Systems/Shinobi!235
merge-requests/256/head
Moe 2020-09-06 19:13:10 +00:00
commit 1fe2c9ea34
4 changed files with 80 additions and 102 deletions

View File

@ -183,87 +183,46 @@ module.exports = function(s,config,lang,app,io){
}
// FTP Server
if(config.ftpServer === true){
const authenticateConnection = (connection) => {
return new Promise((resolve,reject) => {
var username = null;
s.debugLog('client connected: ' + connection.remoteAddress);
connection.on('command:user', function(user, success, failure) {
if (user) {
username = user;
success();
} else {
failure();
}
})
connection.on('command:pass', function(password, success, failure) {
s.basicOrApiAuthentication(username,password,function(err,user){
if(user){
connection._user = user
success(username);
} else {
failure();
}
resolve({
ok: !!user,
username: username,
password: password
})
})
})
})
}
createDropInEventsDirectory()
if(!config.ftpServerPort)config.ftpServerPort = 21
if(!config.ftpServerUrl)config.ftpServerUrl = `ftp://0.0.0.0:${config.ftpServerPort}`
config.ftpServerUrl = config.ftpServerUrl.replace('{{PORT}}',config.ftpServerPort)
const ftpd = require('shinobi-ftpd')
const ftpServer = new ftpd.FtpServer(config.ftpServerUrl, Object.assign({
getInitialCwd: function(connection, callback) {
callback(null, s.dir.dropInEvents + '/' + connection._user.ke)
},
getRoot: function() {
return s.dir.dropInEvents
},
pasvPortRangeStart: 1025,
pasvPortRangeEnd: 1050,
allowUnauthorizedTls: true,
uploadMaxSlurpSize: 7000
},config.ftpServerOptions || {}))
ftpServer.on('error', function(error) {
s.debugLog(['FTP Server error:', error]);
const FtpSrv = require('ftp-srv')
const ftpServer = new FtpSrv({
url: config.ftpServerUrl,
log: require('bunyan').createLogger({
name: 'ftp-srv',
level: 100
}),
})
ftpServer.on('client:connected', async (connection) => {
const response = await authenticateConnection(connection)
if(connection._user){
connection.cwd = s.dir.dropInEvents + connection._user.ke
connection.on('file:stor', async (eventType, data) => {
const fileName = data.file
const pathPieces = fileName.substr(1).split('/')
const groupKey = connection._user.ke
const monitorId = pathPieces[0]
const firstDroppedPart = pathPieces[1]
const monitorEventDropDir = s.dir.dropInEvents + groupKey + '/' + monitorId + '/'
const deleteKey = monitorEventDropDir + firstDroppedPart
onFileOrFolderFound(
monitorEventDropDir + firstDroppedPart,
deleteKey,
{
ke: groupKey,
mid: monitorId
}
)
})
}else{
s.systemLog(`Failed FTP Login Attempt : ${response.username}/${response.password}`)
throw `Failed to Authenticate FTP : ${response.username}/${response.password}`;
}
ftpServer.on('login', ({connection, username, password}, resolve, reject) => {
s.basicOrApiAuthentication(username,password,function(err,user){
if(user){
connection.on('STOR', (error, fileName) => {
if(!fileName)return;
var pathPieces = fileName.replace(s.dir.dropInEvents,'').split('/')
var ke = pathPieces[0]
var mid = pathPieces[1]
var firstDroppedPart = pathPieces[2]
var monitorEventDropDir = s.dir.dropInEvents + ke + '/' + mid + '/'
var deleteKey = monitorEventDropDir + firstDroppedPart
onFileOrFolderFound(monitorEventDropDir + firstDroppedPart,deleteKey,{ke: ke, mid: mid})
})
resolve({root: s.dir.dropInEvents + user.ke})
}else{
// reject(new Error('Failed Authorization'))
}
})
})
ftpServer.on('client-error', ({connection, context, error}) => {
console.log('client-error',error)
})
ftpServer.listen().then(() => {
s.systemLog(`FTP Server running on port ${config.ftpServerPort}...`)
}).catch(function(err){
s.systemLog(err)
})
ftpServer.listen(config.ftpServerPort)
s.systemLog(`FTP Server running on port ${config.ftpServerPort}...`)
}
//add extensions
s.onMonitorInit(onMonitorInit)

View File

@ -555,7 +555,6 @@ module.exports = function(s,config,lang,app){
s.knexQuery({
action: "delete",
table: "Presets",
update: monitorQuery,
where: {
ke: req.params.ke,
name: req.params.stateName,

View File

@ -1429,6 +1429,8 @@ module.exports = function(s,config,lang,app,io){
/**
* API : Get Video File
*/
const videoRowCaches = {}
const videoRowCacheTimeouts = {}
app.get(config.webPaths.apiPrefix+':auth/videos/:ke/:id/:file', function (req,res){
s.auth(req.params,function(user){
const groupKey = req.params.ke
@ -1446,34 +1448,52 @@ module.exports = function(s,config,lang,app,io){
time = s.utcToLocal(time)
}
time = new Date(time)
s.knexQuery({
action: "select",
columns: "*",
table: "Videos",
where: [
['ke','=',groupKey],
['mid','=',req.params.id],
['time','=',time]
],
limit: 1
},(err,r) => {
if(r&&r[0]){
req.dir=s.getVideoDirectory(r[0])+req.params.file
fs.stat(req.dir,function(err,stats){
if (!err){
if(req.query.json === 'true'){
s.closeJsonResponse(res,r[0])
}else{
s.streamMp4FileOverHttp(req.dir,req,res)
}
const cacheName = Object.values(req.params).join('_')
const cacheVideoRow = (videoRow) => {
videoRowCaches[cacheName] = videoRow
clearTimeout(videoRowCacheTimeouts[cacheName])
videoRowCacheTimeouts[cacheName] = setTimeout(() => {
console.log('clear cache',cacheName)
delete(videoRowCaches[cacheName])
},60000)
}
const sendVideo = (videoRow) => {
cacheVideoRow(videoRow)
const filePath = s.getVideoDirectory(videoRow) + req.params.file
fs.stat(filePath,function(err,stats){
if (!err){
if(req.query.json === 'true'){
s.closeJsonResponse(res,videoRow)
}else{
res.end(user.lang['File Not Found in Filesystem'])
s.streamMp4FileOverHttp(filePath,req,res)
}
})
}else{
res.end(user.lang['File Not Found in Database'])
}
})
}else{
res.end(user.lang['File Not Found in Filesystem'])
}
})
}
if(videoRowCaches[cacheName]){
sendVideo(videoRowCaches[cacheName])
}else{
s.knexQuery({
action: "select",
columns: "*",
table: "Videos",
where: [
['ke','=',groupKey],
['mid','=',req.params.id],
['time','=',time]
],
limit: 1
},(err,r) => {
const videoRow = r[0]
if(videoRow){
sendVideo(videoRow)
}else{
res.end(user.lang['File Not Found in Database'])
}
})
}
},res,req);
});
/**

View File

@ -23,7 +23,7 @@
"discord.js": "^12.2.0",
"ejs": "^2.5.5",
"express": "^4.16.4",
"shinobi-ftpd": "0.2.18",
"ftp-srv": "4.3.4",
"http-proxy": "^1.17.0",
"jsonfile": "^3.0.1",
"knex": "^0.21.4",