2019-02-23 17:50:03 +00:00
|
|
|
var fs = require('fs')
|
2019-12-25 07:00:34 +00:00
|
|
|
var exec = require('child_process').exec
|
2019-02-23 06:59:06 +00:00
|
|
|
module.exports = function(s,config,lang,app,io){
|
2021-01-02 18:49:05 +00:00
|
|
|
const {
|
|
|
|
triggerEvent,
|
|
|
|
} = require('./events/utils.js')(s,config,lang)
|
2019-02-23 06:59:06 +00:00
|
|
|
if(config.dropInEventServer === true){
|
2019-08-12 03:42:42 +00:00
|
|
|
if(config.dropInEventForceSaveEvent === undefined)config.dropInEventForceSaveEvent = true
|
2019-02-23 06:59:06 +00:00
|
|
|
if(config.dropInEventDeleteFileAfterTrigger === undefined)config.dropInEventDeleteFileAfterTrigger = true
|
2020-02-19 04:54:48 +00:00
|
|
|
var fileQueueForDeletion = {}
|
|
|
|
var fileQueue = {}
|
|
|
|
var search = function(searchIn,searchFor){
|
|
|
|
return searchIn.indexOf(searchFor) > -1
|
|
|
|
}
|
|
|
|
var getFileNameFromPath = function(filePath){
|
|
|
|
fileParts = filePath.split('/')
|
|
|
|
return fileParts[fileParts.length - 1]
|
|
|
|
}
|
|
|
|
var clipPathEnding = function(filePath){
|
|
|
|
var newPath = filePath + ''
|
|
|
|
if (newPath.substring(newPath.length-1) == "/"){
|
|
|
|
newPath = newPath.substring(0, newPath.length-1);
|
|
|
|
}
|
|
|
|
return newPath;
|
|
|
|
}
|
|
|
|
var processFile = function(filePath,monitorConfig){
|
|
|
|
var ke = monitorConfig.ke
|
|
|
|
var mid = monitorConfig.mid
|
|
|
|
var filename = getFileNameFromPath(filePath)
|
|
|
|
if(search(filename,'.jpg') || search(filename,'.jpeg')){
|
|
|
|
var snapPath = s.dir.streams + ke + '/' + mid + '/s.jpg'
|
|
|
|
fs.unlink(snapPath,function(err){
|
|
|
|
fs.createReadStream(filePath).pipe(fs.createWriteStream(snapPath))
|
2021-01-02 18:49:05 +00:00
|
|
|
triggerEvent({
|
2020-02-19 04:54:48 +00:00
|
|
|
id: mid,
|
|
|
|
ke: ke,
|
|
|
|
details: {
|
|
|
|
confidence: 100,
|
|
|
|
name: filename,
|
|
|
|
plug: "dropInEvent",
|
|
|
|
reason: "ftpServer"
|
|
|
|
},
|
|
|
|
},config.dropInEventForceSaveEvent)
|
|
|
|
})
|
|
|
|
}else{
|
|
|
|
var reason = "ftpServer"
|
|
|
|
if(search(filename,'.mp4')){
|
|
|
|
fs.stat(filePath,function(err,stats){
|
|
|
|
if(err)return;
|
|
|
|
var startTime = stats.ctime
|
|
|
|
var endTime = stats.mtime
|
|
|
|
var shinobiFilename = s.formattedTime(startTime) + '.mp4'
|
|
|
|
var recordingPath = s.getVideoDirectory(monitorConfig) + shinobiFilename
|
|
|
|
var writeStream = fs.createWriteStream(recordingPath)
|
|
|
|
fs.createReadStream(filePath).pipe(writeStream)
|
|
|
|
writeStream.on('finish', () => {
|
|
|
|
s.insertCompletedVideo(s.group[monitorConfig.ke].rawMonitorConfigurations[monitorConfig.mid],{
|
2020-03-03 15:14:32 +00:00
|
|
|
file: shinobiFilename,
|
|
|
|
events: [
|
|
|
|
{
|
|
|
|
id: mid,
|
|
|
|
ke: ke,
|
|
|
|
time: new Date(),
|
|
|
|
details: {
|
|
|
|
confidence: 100,
|
|
|
|
name: filename,
|
|
|
|
plug: "dropInEvent",
|
|
|
|
reason: "ftpServer"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
2020-02-19 04:54:48 +00:00
|
|
|
},function(){
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
var completeAction = function(){
|
2021-01-02 18:49:05 +00:00
|
|
|
triggerEvent({
|
2020-02-19 04:54:48 +00:00
|
|
|
id: mid,
|
|
|
|
ke: ke,
|
|
|
|
details: {
|
|
|
|
confidence: 100,
|
|
|
|
name: filename,
|
|
|
|
plug: "dropInEvent",
|
|
|
|
reason: reason
|
|
|
|
},
|
|
|
|
},config.dropInEventForceSaveEvent)
|
|
|
|
}
|
|
|
|
if(search(filename,'.txt')){
|
|
|
|
fs.readFile(filePath,{encoding: 'utf-8'},function(err,data){
|
|
|
|
if(data){
|
|
|
|
reason = data.split('\n')[0] || filename
|
|
|
|
}else if(filename){
|
|
|
|
reason = filename
|
|
|
|
}
|
|
|
|
completeAction()
|
|
|
|
})
|
|
|
|
}else{
|
|
|
|
completeAction()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var onFileOrFolderFound = function(filePath,deletionKey,monitorConfig){
|
|
|
|
fs.stat(filePath,function(err,stats){
|
|
|
|
if(!err){
|
|
|
|
if(stats.isDirectory()){
|
|
|
|
fs.readdir(filePath,function(err,files){
|
|
|
|
if(files){
|
|
|
|
files.forEach(function(filename){
|
|
|
|
onFileOrFolderFound(clipPathEnding(filePath) + '/' + filename,deletionKey,monitorConfig)
|
|
|
|
})
|
|
|
|
}else if(err){
|
|
|
|
console.log(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}else{
|
|
|
|
if(!fileQueue[filePath]){
|
|
|
|
processFile(filePath,monitorConfig)
|
|
|
|
if(config.dropInEventDeleteFileAfterTrigger){
|
|
|
|
clearTimeout(fileQueue[filePath])
|
|
|
|
fileQueue[filePath] = setTimeout(function(){
|
|
|
|
exec('rm -rf ' + filePath,function(err){
|
|
|
|
delete(fileQueue[filePath])
|
|
|
|
})
|
|
|
|
},1000 * 60 * 5)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(config.dropInEventDeleteFileAfterTrigger){
|
|
|
|
clearTimeout(fileQueueForDeletion[deletionKey])
|
|
|
|
fileQueueForDeletion[deletionKey] = setTimeout(function(){
|
|
|
|
exec('rm -rf ' + deletionKey,function(err){
|
|
|
|
delete(fileQueueForDeletion[deletionKey])
|
|
|
|
})
|
|
|
|
},1000 * 60 * 5)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2020-05-14 01:07:54 +00:00
|
|
|
var createDropInEventsDirectory = function(){
|
2019-02-23 06:59:06 +00:00
|
|
|
if(!config.dropInEventsDir){
|
|
|
|
config.dropInEventsDir = s.dir.streams + 'dropInEvents/'
|
|
|
|
}
|
|
|
|
s.dir.dropInEvents = s.checkCorrectPathEnding(config.dropInEventsDir)
|
|
|
|
//dropInEvents dir
|
|
|
|
if(!fs.existsSync(s.dir.dropInEvents)){
|
|
|
|
fs.mkdirSync(s.dir.dropInEvents)
|
|
|
|
}
|
|
|
|
}
|
2019-02-28 19:27:20 +00:00
|
|
|
var getDropInEventDir = function(monitorConfig){
|
|
|
|
var ke = monitorConfig.ke
|
|
|
|
var mid = monitorConfig.mid
|
|
|
|
var groupEventDropDir = s.dir.dropInEvents + ke
|
|
|
|
var monitorEventDropDir = groupEventDropDir + '/' + mid + '/'
|
|
|
|
return monitorEventDropDir
|
|
|
|
}
|
|
|
|
var onMonitorStop = function(monitorConfig){
|
|
|
|
var ke = monitorConfig.ke
|
|
|
|
var mid = monitorConfig.mid
|
2019-07-08 03:39:41 +00:00
|
|
|
if(s.group[monitorConfig.ke].activeMonitors[monitorConfig.mid].dropInEventWatcher){
|
|
|
|
s.group[monitorConfig.ke].activeMonitors[monitorConfig.mid].dropInEventWatcher.close()
|
|
|
|
delete(s.group[monitorConfig.ke].activeMonitors[monitorConfig.mid].dropInEventWatcher)
|
2019-09-07 19:49:02 +00:00
|
|
|
var monitorEventDropDir = getDropInEventDir(monitorConfig)
|
|
|
|
s.file('deleteFolder',monitorEventDropDir + '*')
|
2019-02-28 19:27:20 +00:00
|
|
|
}
|
2019-09-07 19:49:02 +00:00
|
|
|
}
|
|
|
|
var createDropInEventDirectory = function(e,callback){
|
|
|
|
var directory = s.dir.dropInEvents + e.ke + '/'
|
|
|
|
fs.mkdir(directory,function(err){
|
|
|
|
s.handleFolderError(err)
|
|
|
|
directory = s.dir.dropInEvents + e.ke + '/' + (e.id || e.mid) + '/'
|
|
|
|
fs.mkdir(directory,function(err){
|
|
|
|
s.handleFolderError(err)
|
2020-02-19 04:54:48 +00:00
|
|
|
exec('rm -rf "' + directory + '*"',function(){})
|
2019-09-07 19:49:02 +00:00
|
|
|
callback(err,directory)
|
|
|
|
})
|
|
|
|
})
|
2019-02-28 19:27:20 +00:00
|
|
|
}
|
2019-02-23 06:59:06 +00:00
|
|
|
var onMonitorInit = function(monitorConfig){
|
|
|
|
var ke = monitorConfig.ke
|
|
|
|
var mid = monitorConfig.mid
|
|
|
|
var groupEventDropDir = s.dir.dropInEvents + ke
|
2020-02-19 04:54:48 +00:00
|
|
|
createDropInEventDirectory(monitorConfig,function(err,monitorEventDropDir){})
|
2019-02-23 06:59:06 +00:00
|
|
|
}
|
2019-02-28 04:17:49 +00:00
|
|
|
// FTP Server
|
2019-02-23 17:50:03 +00:00
|
|
|
if(config.ftpServer === true){
|
2020-05-14 01:07:54 +00:00
|
|
|
createDropInEventsDirectory()
|
2019-02-24 06:01:53 +00:00
|
|
|
if(!config.ftpServerPort)config.ftpServerPort = 21
|
|
|
|
if(!config.ftpServerUrl)config.ftpServerUrl = `ftp://0.0.0.0:${config.ftpServerPort}`
|
2022-01-29 08:47:25 +00:00
|
|
|
if(!config.ftpServerPasvUrl)config.ftpServerPasvUrl = config.ftpServerUrl.replace(/.*:\/\//, '').replace(/:.*/, '');
|
2022-01-26 19:45:15 +00:00
|
|
|
if(!config.ftpServerPasvMinPort)config.ftpServerPasvMinPort = 10050;
|
|
|
|
if(!config.ftpServerPasvMaxPort)config.ftpServerPasvMaxPort = 10100;
|
2019-02-24 06:01:53 +00:00
|
|
|
config.ftpServerUrl = config.ftpServerUrl.replace('{{PORT}}',config.ftpServerPort)
|
2020-09-06 18:55:42 +00:00
|
|
|
const FtpSrv = require('ftp-srv')
|
2022-01-26 19:45:15 +00:00
|
|
|
|
2020-09-06 18:55:42 +00:00
|
|
|
const ftpServer = new FtpSrv({
|
|
|
|
url: config.ftpServerUrl,
|
2021-03-28 18:04:42 +00:00
|
|
|
// pasv_url must be set to enable PASV; ftp-srv uses its known IP if given 127.0.0.1,
|
|
|
|
// and smart clients will ignore the IP anyway. Some Dahua IP cams require PASV mode.
|
|
|
|
// ftp-srv just wants an IP only (no protocol or port)
|
2022-01-26 19:45:15 +00:00
|
|
|
pasv_url: config.ftpServerPasvUrl,
|
|
|
|
pasv_min: config.ftpServerPasvMinPort,
|
|
|
|
pasv_max: config.ftpServerPasvMaxPort,
|
|
|
|
greeting: "Shinobi FTP dropInEvent Server says hello!",
|
2020-09-06 18:55:42 +00:00
|
|
|
log: require('bunyan').createLogger({
|
|
|
|
name: 'ftp-srv',
|
|
|
|
level: 100
|
|
|
|
}),
|
2019-02-24 06:01:53 +00:00
|
|
|
})
|
2019-02-23 17:50:03 +00:00
|
|
|
|
2020-09-06 18:55:42 +00:00
|
|
|
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
|
2020-12-28 18:22:37 +00:00
|
|
|
onFileOrFolderFound(monitorEventDropDir + firstDroppedPart,deleteKey,Object.assign(s.group[ke].rawMonitorConfigurations[mid],{}))
|
2020-09-06 18:55:42 +00:00
|
|
|
})
|
|
|
|
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)
|
2019-02-24 06:01:53 +00:00
|
|
|
})
|
2019-02-27 02:34:04 +00:00
|
|
|
}
|
2019-02-28 04:17:49 +00:00
|
|
|
//add extensions
|
|
|
|
s.onMonitorInit(onMonitorInit)
|
2019-02-28 19:27:20 +00:00
|
|
|
s.onMonitorStop(onMonitorStop)
|
2019-02-28 04:17:49 +00:00
|
|
|
}
|
|
|
|
// SMTP Server
|
|
|
|
// allow starting SMTP server without dropInEventServer
|
|
|
|
if(config.smtpServer === true){
|
2019-08-13 23:21:39 +00:00
|
|
|
if(config.smtpServerHideStartTls === undefined)config.smtpServerHideStartTls = null
|
2019-02-28 04:17:49 +00:00
|
|
|
var SMTPServer = require("smtp-server").SMTPServer;
|
|
|
|
if(!config.smtpServerPort && (config.smtpServerSsl && config.smtpServerSsl.enabled !== false || config.ssl)){config.smtpServerPort = 465}else if(!config.smtpServerPort){config.smtpServerPort = 25}
|
2020-08-11 16:16:53 +00:00
|
|
|
config.smtpServerOptions = config.smtpServerOptions ? config.smtpServerOptions : {}
|
|
|
|
var smtpOptions = Object.assign({
|
2020-06-02 05:17:36 +00:00
|
|
|
logger: config.debugLog || config.smtpServerLog,
|
2019-08-13 23:21:39 +00:00
|
|
|
hideSTARTTLS: config.smtpServerHideStartTls,
|
2019-02-28 04:17:49 +00:00
|
|
|
onAuth(auth, session, callback) {
|
|
|
|
var username = auth.username
|
|
|
|
var password = auth.password
|
2019-04-06 05:27:22 +00:00
|
|
|
s.basicOrApiAuthentication(username,password,function(err,user){
|
2019-02-28 04:17:49 +00:00
|
|
|
if(user){
|
|
|
|
callback(null, {user: user.ke})
|
2019-02-27 02:34:04 +00:00
|
|
|
}else{
|
2019-02-28 04:17:49 +00:00
|
|
|
callback(new Error(lang.failedLoginText2))
|
2019-02-27 02:34:04 +00:00
|
|
|
}
|
|
|
|
})
|
2019-02-28 04:17:49 +00:00
|
|
|
},
|
|
|
|
onRcptTo(address, session, callback) {
|
|
|
|
var split = address.address.split('@')
|
|
|
|
var monitorId = split[0]
|
|
|
|
var ke = session.user
|
2020-05-19 23:56:21 +00:00
|
|
|
if(s.group[ke] && s.group[ke].rawMonitorConfigurations[monitorId] && s.group[ke].activeMonitors[monitorId].isStarted === true){
|
2019-08-13 23:21:39 +00:00
|
|
|
session.monitorId = monitorId
|
2019-02-28 04:17:49 +00:00
|
|
|
}else{
|
|
|
|
return callback(new Error(lang['No Monitor Exists with this ID.']))
|
|
|
|
}
|
|
|
|
callback()
|
2019-08-13 23:21:39 +00:00
|
|
|
},
|
|
|
|
onData(stream, session, callback) {
|
|
|
|
if(session.monitorId){
|
|
|
|
var ke = session.user
|
|
|
|
var monitorId = session.monitorId
|
2020-01-18 07:20:16 +00:00
|
|
|
var details = s.group[ke].rawMonitorConfigurations[monitorId].details
|
2019-08-13 23:21:39 +00:00
|
|
|
var reasonTag = 'smtpServer'
|
|
|
|
var text = ''
|
|
|
|
stream.on('data',function(data){
|
|
|
|
text += data.toString()
|
|
|
|
}) // print message to console
|
|
|
|
stream.on("end", function(){
|
|
|
|
var contentPart = text.split('--PartBoundary12345678')
|
|
|
|
contentPart.forEach(function(part){
|
|
|
|
var parsed = {}
|
|
|
|
var lines = part.split(/\r?\n/)
|
|
|
|
lines.forEach(function(line,n){
|
|
|
|
var pieces = line.split(':')
|
|
|
|
if(pieces[1]){
|
|
|
|
var nextLine = lines[n + 1]
|
|
|
|
var keyName = pieces[0].trim().toLowerCase()
|
|
|
|
pieces.shift()
|
|
|
|
var parsedValue = pieces.join(':')
|
|
|
|
parsed[keyName] = parsedValue
|
|
|
|
}
|
|
|
|
})
|
|
|
|
if(parsed['content-type'] && parsed['content-type'].indexOf('image/jpeg') > -1){
|
|
|
|
// console.log(lines)
|
|
|
|
}
|
|
|
|
if(parsed['alarm event']){
|
|
|
|
reasonTag = parsed['alarm event']
|
|
|
|
}else if(parsed.subject){
|
|
|
|
reasonTag = parsed.subject
|
|
|
|
}
|
|
|
|
})
|
2021-01-02 18:49:05 +00:00
|
|
|
triggerEvent({
|
2019-08-13 23:21:39 +00:00
|
|
|
id: monitorId,
|
|
|
|
ke: ke,
|
|
|
|
details: {
|
|
|
|
confidence: 100,
|
|
|
|
name: 'smtpServer',
|
|
|
|
plug: "dropInEvent",
|
|
|
|
reason: reasonTag
|
2020-01-18 07:20:16 +00:00
|
|
|
},
|
2019-08-13 23:21:39 +00:00
|
|
|
},config.dropInEventForceSaveEvent)
|
|
|
|
callback()
|
|
|
|
})
|
|
|
|
}else{
|
|
|
|
callback()
|
|
|
|
}
|
2019-02-27 02:34:04 +00:00
|
|
|
}
|
2020-08-11 16:16:53 +00:00
|
|
|
},config.smtpServerOptions)
|
2019-02-28 04:17:49 +00:00
|
|
|
if(config.smtpServerSsl && config.smtpServerSsl.enabled !== false || config.ssl && config.ssl.cert && config.ssl.key){
|
|
|
|
var key = config.ssl.key || fs.readFileSync(config.smtpServerSsl.key)
|
|
|
|
var cert = config.ssl.cert || fs.readFileSync(config.smtpServerSsl.cert)
|
|
|
|
smtpOptions = Object.assign(smtpOptions,{
|
|
|
|
secure: true,
|
|
|
|
key: config.ssl.key,
|
|
|
|
cert: config.ssl.cert
|
2019-02-23 17:50:03 +00:00
|
|
|
})
|
|
|
|
}
|
2019-02-28 04:17:49 +00:00
|
|
|
var server = new SMTPServer(smtpOptions)
|
|
|
|
server.listen(config.smtpServerPort,function(){
|
|
|
|
s.systemLog(`SMTP Server running on port ${config.smtpServerPort}...`)
|
|
|
|
})
|
2019-02-23 06:59:06 +00:00
|
|
|
}
|
2021-11-14 16:38:22 +00:00
|
|
|
require('./dropInEvents/mqtt.js')(s,config,lang,app,io)
|
2019-02-23 06:59:06 +00:00
|
|
|
}
|